简体   繁体   中英

EF6 One-to-One Optional Relationship one-directional navigation properties

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:

  1. You can specify an required relationship without specifying the type, like .WithRequired() .
  2. When using 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:

  1. 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; } } 
  2. Entity configuration:

     public class PersonConfig:EntityTypeConfiguration<Person> { public PersonConfig() { HasOptional(t => t.User).WithRequired().WillCascadeOnDelete(); } } 
  3. 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()); } } 
  4. 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); } 
  5. 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); } 
  6. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM