EF6一对一可选关系单向导航属性

时间:2016-04-10 00:22:54

标签: c# entity-framework ef-code-first entity-framework-6 ef-fluent-api

我正在处理的项目中有以下域模型,它们是

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; }
}

我基本上有一个Person实体和一个User实体,Person可以在没有User的情况下存在,但如果没有UserPerson不能存在Person 1}}。我也只希望EF中的关系单向加载(即当我加载User实体时我想要导航属性到User但不是另一种方式)

我发现我必须在两个对象上创建关系属性来实现关系映射,当然不希望这个或者在一个方向上检查NULL的开销,我宁愿{{1}实体没有Person属性。

任何人都可以帮助定义正确的模型和关系映射,以便在运行时生成正确的EF Code-First配置和对象模型,我尝试了以下内容:

modelBuilder.Entity<Person>()
    .HasOptional(t => t.User)
    .WithRequired(t => t.Person)
    .Map(x => x.MapKey("PersonId"))
    .WillCascadeOnDelete();

此操作正在加载具有Person属性为NULL的User实体

如果有人能提供帮助,我们将不胜感激

1 个答案:

答案 0 :(得分:1)

您需要正确配置实体:

  1. 您可以指定所需的关系,而无需指定类型,例如.WithRequired()
  2. 使用one-to-one关系时,key属性的名称在两个实体中都必须相同。
  3. 因此,您只需使用HasOptional(t => t.User).WithRequired();即可实现所需目标。

    为了完整起见,我在下面添加(或多或少)完整代码:

    1. 实体:

      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. 实体配置:

      public class PersonConfig:EntityTypeConfiguration<Person>
      {
          public PersonConfig()
          {
              HasOptional(t => t.User).WithRequired().WillCascadeOnDelete();
          }
      }
      
    3. 数据库上下文

      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. 生成的初始迁移(使用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. 种子配置:

      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. 用法:

      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
      */