I have som mapping problem with EF.
This is my classes
public class User{
public Guid Id { get; set; }
// Fullname of the user account owner
public string Name { get; set; }
public string Email { get; set; }
public string Username { get; set; }
public Player Player { get; set; }
}
public class Player
{
public Guid Id { get; set; }
public string Name { get; set; }
public virtual User User { get; set; }
}
It works fine, but now I want to create the navigation property Player and User in this classes. I have this Fluent code:
modelBuilder.Entity<User>()
.HasOptional(x => x.Player)
.WithOptionalDependent(x => x.User)
.Map(x => x.MapKey("Username"));
But I only get this error message, and I have no ide what's wrong.
Each property name in a type must be unique. Property name 'Username'
was already defined.
My DB setup looks like the classes, in the player table the Name is unique. It's not unique in the User table. A user can exist without a player and vice versa. (Actully I don't want any User property inside the Player class but I think it's a requierment?!)
I think it's complaining about the fact that UserName is already a property in the object model. See the docs for the Map() method:
From http://msdn.microsoft.com/en-us/library/system.data.entity.modelconfiguration.configuration.foreignkeynavigationpropertyconfiguration.map%28v=vs.103%29:
Configures the relationship to use foreign key property(s) that are
not exposed in the object model. The column(s) and table can be
customized by specifying a configuration action. If an empty
configuration action is specified then column name(s) will be
generated by convention. If foreign key properties are exposed in the
object model then use the HasForeignKey method. Not all relationships
support exposing foreign key properties in the object model.
Remove the modelBuilder code and mark the PrimaryKey as a ForeignKey on the dependent table. For example if Players don't exist without a User:
public class User
{
public Guid Id { get; set; }
// Fullname of the user account owner
public string Name { get; set; }
public string Email { get; set; }
public string Username { get; set; }
public Player Player { get; set; }
}
public class Player
{
[ForeignKey("User")]
public Guid Id { get; set; }
public string Name { get; set; }
public virtual User User { get; set; }
}
The ForeignKey attribute tells EF which side of the one-to-one is dependent, allowing it to map it properly.
If your columns in the database has the same name as the properties of your model you don't need to map the property ".Map(x => x.MapKey("Username"));" EF already mapped the property "Username" using the convention and is because of that the EF is complaining
With your entities
...I just like to do it the other way around:
modelBuilder.Entity<Player>()
.HasRequired(i => i.User)
.WithRequiredDependent(i => i.Player);
or this (optional):
modelBuilder.Entity<Player>()
.HasRequired(i => i.User)
.WithOptional(x => x.Player);
Related
I'm creating my database using code-first and entity framework core, I have a 1:1 relationship, but in this relationship, I have a navigation property in both entities, this is my first entity:
public class User
{
[Key]
public string Email { get; set; }
public virtual Mac Mac { get; set; }
public virtual Gender Gender { get; set; }
}
and this is my second entity:
public class Mac
{
[Key]
public Guid Id { get; set; }
public DateTime CreationDate { get; set; }
public HashSet<MacsUsers> MacsUsers { get; set; }
public string UserEmail { get; set; }
public User User { get; set; }
}
and this is my dbContext configuration:
builder.Entity<User>().HasOne(u => u.Mac)
.WithOne()
.HasForeignKey<Mac>(g => g.UserEmail);
THE REASON why I have these navigation properties in both entities is that I have a query in which I retrieve data from Mac by using User entity like this:
foreach (var item in ListTupla)
{
item.CreationDate = listUser.FirstOrDefault(u => u.Mac.Id == item.MacId).Mac.User.CreationDate;
item.MacUserTalked = listUser.FirstOrDefault(u => u.Mac.Id == item.MacId).Mac.User.Email;//here Mac.User
item.MacUserWhoTalks = listUser.FirstOrDefault(u => u.Mac.Id == item.MacId).Email;
item.Name = listUser.FirstOrDefault(u => u.Mac.Id == item.MacId).Mac.User.Name; //here Mac.User
this is exactly the message warning: The foreign key property 'Mac.UserEmail1' was created in shadow state because a conflicting property with the simple name 'UserEmail' exists in the entity type, but is either not mapped, is already used for another relationship, or is incompatible with the associated primary key type. See https://aka.ms/efcore-relationships for information on mapping relationships in EF Core
I have found a solution is putting the virtual in the navigation property but it does not work for me, any comment?
I added public virtual in front of my reference navigation properties and it solved the issue.See this image please
I try to get navigational properties to work between a object that I own and maintain and a view that is controlled by a other party. Iam using a MS SQL Server database.
I have 2 models
public class Trajectory
{
public Guid Id { get; set; }
//Some more data
public Contact Contact { get; set; }
public Guid ContactId { get; set; }
}
public class Contact
{
public Guid Id { get; set; }
public string FullName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Trajectory> Trajectories {get;set;}
}
The first one is a model which is created and migrate with entity. The second one is a external view which I have no control over.
So I did this in my model builder:
modelBuilder.Entity<Contact>()
.HasNoKey()
.ToView("SomeView");
And for my other entity:
builder.HasOne(e => e.Contact)
.WithMany(e => e.Trajectories)
.HasForeignKey(e => e.ContactId );
When I ran this migration it failed with a null pointer. When I removed the HasNoKey() from the first part I got a migration. When I ran the update-database command I got the following error:
Foreign key 'FK_Trajectories_SomeView_ContactId' references object 'SomeView' which is not a user table.
Could not create constraint or index. See previous errors.
I'am kind of lost with how I can create a navigational property to the view?
I have an entity User that has two properties CreatedBy and UpdatedBy both referencing User. By default, EF assumes that these two as a one to one relation to each other. I get the following error message:
Message: System.InvalidOperationException : The child/dependent side could not be determined for the one-to-one relationship that was detected between 'User.CreatedBy' and 'User.UpdatedBy'. To identify the child/dependent side of the relationship, configure the foreign key property. If these navigations should not be part of the same relationship configure them without specifying the inverse. See http://go.microsoft.com/fwlink/?LinkId=724062 for more details.
Currently, I have a class like this:
public class User
{
public int Id { get; set; }
public int? CreatedById { get; set; }
public User CreatedBy { get; set; }
public int? UpdatedById { get; set; }
public User UpdatedBy { get; set; }
}
Basically, here is what I am trying:
The created and updated would have no relation to each other (no navigation/inverse property needed)
Any number of users can have the same CreatedBy and any number of users can have the same UpdatedBy.
How can I ask EF to just ignore the navigation property? The main reason I have CreatedBy is so I can use Include(u => u.CreatedBy) later on. I know using IEnumerable<User> AllCreatedUsers property would solve this but I did not want to create an IEnumerable for each in my entity. Is there any way to do this with fluent API?
Here is what I tried:
modelBuilder.Entity<User>()
.Property<IEnumerable<User>>("AllCreatedUsers");
modelBuilder.Entity<User>().HasOne(u => u.CreatedBy)
.WithMany(u => EF.Property<IEnumerable<User>>(u, "AllCreatedUsers"));
You need to configure two Single Navigation Property relationships by using parameterless WithMany method overload:
modelBuilder.Entity<User>()
.HasOne(u => u.CreatedBy)
.WithMany();
modelBuilder.Entity<User>()
.HasOne(u => u.UpdatedBy)
.WithMany();
You ForeignKey data annotation for both the properties.
public class User
{
public int Id { get; set; }
public int? CreatedById { get; set; }
[ForeignKey("CreatedById")]
public User CreatedBy { get; set; }
public int? UpdatedById { get; set; }
[ForeignKey("UpdatedById")]
public User UpdatedBy { get; set; }
}
I am currently making a web app for MVC 3 using Entity Framework but I'm a beginner and I can't make the Code First mapping work properly and for some reason my Visual Studio doesn't have Database First and Model First functionality.
I have three model classes: Contacto, Proveedor and Usuario, each one of them corresponding to a table on an database existing database and I want to make those classes with Code First to map to this database. Contacto has a one-to-one relationship with Proveedor and Usuario. I declared the model classes like this:
public class Contacto
{
public int ID { get; set; }
public string Nombre { get; set; }
public string Telefono { get; set; }
public Proveedor ProveedorID { get; set; }
public Usuario UsuarioID { get; set; }
}
public class Proveedor
{
public short ID { get; set; }
public string NombreProveedor {get;set;}
}
public class Usuario
{
public short ID { get; set; }
public string NombreUsuario {get;set;}
}
The context class is the following:
public class Contexto : DbContext
{
public DbSet<Contacto> Contactos { get; set; }
public DbSet<Proveedor> Proveedores { get; set; }
public DbSet<Usuarios> Usuarios { get; set; }
}
I made a controller and view with CRUD methods but when the code gets to the EditorFor for the Proveedor attribute in Contacto I get a Invalid column name 'ProveedorID' and the same for UsuarioID. Changing the table names on the existing database doesn't fix this but sometimes makes the Invalid column name error refer to Contacto_ID instead of ProveedorID.
How do I make the reference to the Proveedor and Usuario model in Contacto work? And how override the automatic table mapping and specify the mapping manually? The name conventions don't work well in Spanish and don't detect properly that there is a relationship in a database.
When you don't tell EF anything about how entities and properties map to table and column names, it will make its own assumptions by following a number of conventions. One of them is to assume that a foreign key column is the name of the referred entity with _ID appended to it.
If you don't want EF to follow these default conventions, you have to add your own mappings. I'll show an example of how you can do this.
First, I'd remove the "ID" part from the reference properties, and add primitive foreign key properties to the Contacto class:
public class Contacto
{
public int ID { get; set; }
public string Nombre { get; set; }
public string Telefono { get; set; }
public short ProveedorID { get; set; }
public Proveedor Proveedor { get; set; }
public short UsuarioID { get; set; }
public Usuario Usuario { get; set; }
}
One way to tell EF about database names of entities and properties is fluent mapping. You can either do this in the OnModelCreating override of your context class, or in an EntityTypeConfiguration override:
public class ContactoMap : EntityTypeConfiguration<Contacto>
{
public ContactoMap()
{
ToTable("tblContacto");
Property(c => c.ProveedorID).HasColumnName("ProveedorId");
HasRequired(x => x.Proveedor).WithMany().HasForeignKey(c => c.ProveedorID);
Property(c => c.UsuarioID).HasColumnName("UsuarioId");
HasRequired(x => x.Usuario).WithMany().HasForeignKey(c => c.UsuarioID);
}
}
I just make up some names, since you don't mention which database names you want to have, but you get the idea.
The final step is to add this mapping to the model by overriding OnModelCreating in the context:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ContactoMap());
}
By the way, if you have these properties like ProveedorID, EF will also infer these as foreign keys to the matching entity. Only when you don't include these primitive foreign key properties, EF will expect the column names with underscores in the database.
Hi I am having a problem with a simple EF 4.1 code first model.
I have a class person and a class survey that are bidirectionally linked. The database model is correct but I always get this error:
Unable to determine the principal end of an association between the types 'DAL.Models.Survey' and 'DAL.Models.Person'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
Class Person
[Key]
public Guid Id { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string Email { get; set; }
public virtual Survey Survey { get; set; }
Class Survey
[Key]
public Guid Id { get; set; }
public bool IsFinished { get; set; }
public virtual Person Person { get; set; }
Datacontext:
modelBuilder.Entity<Survey>().HasRequired(s => s.Person).WithOptional().WillCascadeOnDelete(true);
Can anyone help please
You should define the other navigation property in your mapping since you have it in the model. Otherwise EF will create a second (one-to-many) association:
modelBuilder.Entity<Survey>()
.HasRequired(s => s.Person)
.WithOptional(p => p.Survey)
.WillCascadeOnDelete(true);
I think you have to specify either a foreign key property through HasForeignKey or foreign key column name using Map. Something like this:
modelBuilder.Entity<Survey>()
.HasRequired(s => s.Person)
.WithOptional()
.WillCascadeOnDelete(true)
.Map(m => m.MapKey("fk_column"));