I have the following Domain models in a project I am working on, they are
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
public virtual User { get; set; }
}
public class User
{
public int Id { get; set; }
public string LoginName { get; set; }
public string Password { get; set; }
}
I basically have a Person
entity and a User
entity, a Person
can exist without a User
but a User
cannot exist without a Person
. I also only want the relationship in EF to be loaded unidirectional (ie when i load the Person
entity I want a navigation property to User
but NOT the other way)
I am finding that I have to create the relational properties on both objects to achieve the relationship mapping and of course do not want this or the overhead of having to check for NULL in one direction, i would rather the User
entity did not have its Person
property.
Could anyone help with defining the correct model and relationship mapping to generate the correct EF Code-First configuration and object model at runtime please, I have tried the following:
modelBuilder.Entity<Person>()
.HasOptional(t => t.User)
.WithRequired(t => t.Person)
.Map(x => x.MapKey("PersonId"))
.WillCascadeOnDelete();
Al that this acheives is loading the Person
entity with the User
property of NULL
If anyone can help it will be greatly appreciated
You need to configure the entities properly:
.WithRequired()
. one-to-one
relationship, name of the key
property needs tobe same in both entities. Thus, you can simply achieve what you want by using HasOptional(t => t.User).WithRequired();
.
For the sake of completeness, I am adding the (more or less) full code below:
The entities:
public class Person { public int Id { get; set; } public string FirstName { get; set; } public string Surname { get; set; } public virtual User User { get; set; } } public class User { public int Id { get; set; } public string LoginName { get; set; } public string Password { get; set; } }
Entity configuration:
public class PersonConfig:EntityTypeConfiguration<Person> { public PersonConfig() { HasOptional(t => t.User).WithRequired().WillCascadeOnDelete(); } }
Database context
public class MyDbContext:DbContext { public DbSet<Person> People { get; set; } public DbSet<User> Users { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new PersonConfig()); } }
Generated initial migration(using add-migration
):
public override void Up() { CreateTable( "dbo.People", c => new { Id = c.Int(nullable: false, identity: true), FirstName = c.String(), Surname = c.String(), }) .PrimaryKey(t => t.Id); CreateTable( "dbo.Users", c => new { Id = c.Int(nullable: false), LoginName = c.String(), Password = c.String(), }) .PrimaryKey(t => t.Id) .ForeignKey("dbo.People", t => t.Id, cascadeDelete: true) .Index(t => t.Id); }
Seed configuration:
protected override void Seed(EF.MyDbContext context) { var person1 = new Person {Id= 1, FirstName = "Andrew", Surname = "Peters" }; var person2 = new Person {Id= 2, FirstName = "Brice", Surname = "Lambson" }; var person3 = new Person {Id= 3, FirstName = "Rowan", Surname = "Miller" }; context.People.AddOrUpdate(p => p.Id, person1, person2, person3); var user1 = new User { Id = 1, LoginName = "Andrew", Password = "Peters" }; var user3 = new User { Id = 3, LoginName = "Rowan", Password = "Miller" }; context.Users.AddOrUpdate(p => p.Id, user1, user3); }
Usage:
MyDbContext ctx = new MyDbContext(); ctx.People.ToList().ForEach(person => { System.Console.WriteLine($"Id:{person.Id}, Name: {person.FirstName} {person.Surname}"); if (person.User != null) { System.Console.WriteLine($"Found user, Id:{person.User.Id}, " + $"Login: {person.User.LoginName}, Password: {person.User.Password}"); } }); /* Output: Id:1, Name: Andrew Peters Found user, Id:1, Login: Andrew, Password: Peters Id:2, Name: Brice Lambson Id:3, Name: Rowan Miller Found user, Id:3, Login: Rowan, Password: Miller */
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.