entity-framework - Entity Framework 4.1 Fluent API 中带有连接表和可选关系的一对多

标签 entity-framework entity-framework-4.1 ef-code-first

再次使用无法更改的旧数据库,并使用带有 Fluent API 的 Entity Framework 4.1 仅读取数据。

public class Client
{
  [Key]
  public int ClientID { get; set; }
  public string Name { get; set ;}

  public virtual ICollection<Phone> Phones { get; set; }
}

public class Phone
{
  [Key]
  public int PhoneID { get; set; }
  public string Number { get; set; }

  public virtual Client Client { get; set; }
}

public class ClientPhone
{
  [Key]
  [Column(Order=0)]
  public int ClientID { get; set; }

  [Key]
  [Column(Order=1)]
  public int PhoneID { get; set; }
}

我希望客户端有很多电话,但电话应该只有一个可选的客户端。
注意:电话应该只有 0|1 个客户端。我不想要多对多。
所以我尝试了以下方法:
modelBuilder.Entity<Client>()
  .HasMany(c => c.Phones)
  .WithOptional(p => p.Client)
  .Map(m =>
    {
      m.MapKey("ClientID");
      m.ToTable("ClientPhone");
    });

modelBuilder.Entity<Phone>()
  .HasOptional(p => p.Client)
  .WithMany(c => c.Phones)
  .Map(m =>
    {
      m.MapKey("PhoneID");
      m.ToTable("ClientPhone");
    });

我已经尝试了几个排列,通常会得到一个关于“类型中的每个属性名称必须是唯一的”的错误。

谢谢您的帮助。

编辑答案

以下是我对实体类所做的修改。可以从 导航一个客户端到多个电话 来自 一机一机 ,但您必须通过 ClientPhone 连接表。
[Table("Client")]
public class Client
{
  [Key]
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  public int ClientID { get; set; }

  public string Name { get; set ;}

  public virtual ICollection<Phone> Phones { get; set; } // Client has * Phones
}

[Table("Phone")]
public class Phone
{
  [Key]
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  public int PhoneID { get; set; }

  public string Number { get; set; }

  public virtual Client Client { get; set; } // Phone has 0|1 Client
}

[Table("ClientPhone")]
public class ClientPhone
{
  // Removed the Key attribute
  public int ClientID { get; set; }

  [Key] // Left the Key on the 0|1 side
  [ForeignKey("Phone")]
  public int PhoneID { get; set; }

  public virtual Client Client { get; set; } // One Client
  public virtual Phone Phone { get; set; } // One Phone
}

最佳答案

您不需要在这里指定两次电话和客户端之间的关系。只使用一个这样的。

modelBuilder.Entity<Client>().HasMany(c => c.Phones).WithMany(i => i.Clients)
                .Map(t => t.MapLeftKey("PhoneID")
                    .MapRightKey("ClientID")
                    .ToTable("ClientPhone"));

您不需要模型来映射“ClientPhone”等关系表,因为 EF 会处理它。如果您有旧数据库,您可以按照我的回答自定义您的映射。正如@Ladislav Mrnka 所说,对于数据库级别的一对多关系,您不想为关系保留单独的表。为了那个原因 ,
public class Client
{
  [Key]
  public int ClientID { get; set; }
  public string Name { get; set ;}

  public virtual ICollection<Phone> Phones { get; set; }
}

public class Phone
{
  [Key]
  public int PhoneID { get; set; }
  public string Number { get; set; }

  public virtual Client Client { get; set; }
}

这对EF就足够了。它将创建两个表 客户 ID 栏目电话 表保持关系。

问题是您的旧数据库中有单独的关系表。我认为旧数据库是为多对多关系定义的。再次考虑您的域逻辑。

如果你想保持一对多的关系,我认为你可以在域级别定义多对多关系(电话有很多客户,客户在模型类中有很多电话)并在你的业务层添加验证以保持只有一个 客户对于 电话 .

关于entity-framework - Entity Framework 4.1 Fluent API 中带有连接表和可选关系的一对多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7034185/

相关文章:

c# - Entity Framework - Distinct 和 Max 生成巨大(且缓慢)的查询

c# - Entity Framework 以不确定的方式未经许可删除有效内容?

c# - 上传到托管服务器后 Entity Framework 连接错误

c# - 使用 EF Code First 的循环和多级联路径

entity-framework - EF 4.3 迁移 - 如何生成降级脚本?

entity-framework - 在运行时更改表名

asp.net-mvc - 当目标是在 View 中显示此图像时,我应该在模型中使用哪种图像?

c# - 使用 EF 将数据插入 SQL 数据库

c# - Entity Framework 代码优先 - 无法在对象 'db' 中插入重复键

c# - DbSet.FirstOrDefault()?