【问题标题】:How to map a Value Type which has a reference to an entity?如何映射引用实体的值类型?
【发布时间】:2013-06-20 22:24:21
【问题描述】:

我遇到了实体框架中的映射问题。

我有以下课程(简化):

public class Building
{

    public int ID { get; set; }     
    // *.. snip..* other properties
    public Location Location { get; private set; }
}

public class Location
{
    public string Street {get; set;}
    public Country country {get; set}
}
public class Country
{
    public int ID { get; set; } 
    public string Name { get; set; } 
}

Building 和 Country 是实体,它们保存在数据库中。 Location 是一个值类型,应该映射到与 Building 相同的表。

但是,当我以这种方式映射它时,实体框架也想将 Location 映射到一个表并且抱怨它没有 Key。我不想给它钥匙,因为它属于大楼,根本不应该是一个实体。

我看到过一些变通方法,说您需要将 Country 放在 Building 类中,但这感觉不太好(并且在语义上完全是错误的)。

我正在使用实体框架 5

【问题讨论】:

  • 您正在寻找complex types
  • 是的,我知道,问题是一旦复杂类型引用了实体,EF 也想将复杂类型放入表中
  • 真是个好问题。实际上,我通常把重点放在域逻辑上,我根本不关心 ORM 如何持久化数据(因此我不会认为在 Location 中添加 Id 列是一个大问题)。如果我真的必须关心数据的存储方式,我会考虑不将域对象与 ORM 实体混合,通过创建一个特定的层来持久化(创建实体来参与 ORM),尽管这可能会使架构更加复杂。如果您得出结论,请告诉我们,也许 CQRS 可以解决这个问题。
  • 是的,最后,我刚刚摆脱了 EF。没有 ORM 更简单:-)
  • 您可以使用 NHibernate 代替 EF。在这里你可以做这些事情。

标签: c# .net entity-framework entity-framework-5


【解决方案1】:

自从Entity Framework Core 2 发布以来,现在可以使用owned entities 实现这一目标。

您的配置如下所示:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // ...
    modelBuilder.Entity<Building>().OwnsOne(x => x.Location);
    modelBuilder.Entity<Location>().HasOne(x => x.Country);
    // ...
}

这样,来自Location 类的属性将成为Building 类映射到的表的一部分。这意味着您将只有BuildingCountry 类的表,而Building 表将具有Country 表的外键。

我知道你已经很久没有发布这个问题了,但我认为这个答案可能对遇到这个问题的人有所帮助。

【讨论】:

    【解决方案2】:

    在我看来,实体框架不应该允许这种情况。

    我了解您不会将位置视为实体,但将实体引用添加到复杂类型似乎也不是一种可靠的方法。一座建筑与一个国家的关系非常直接。一座建筑属于一个国家。因此,建筑模型应包含国家/地区 ID。您希望映射什么?

    如果您希望表 Building 只有三列 ID, Street, CountryId 并且您仍想保存 Location 模型,那么您应该使用以下复杂类型。

    public class Location
    {
        public string Street {get; set;}
        public int countryId {get; set}
    }
    

    但是,如果您希望 Building 表包含模型 Country 中的所有字段,那么这可能会导致一些棘手的情况,例如如果您想向 Country 模型添加新字段或如果您想添加其他根据新的商业案例将复杂类型或实体添加到您的国家/地区模型。

    这些情况会混淆关系概念,并且会在没有任何有意义的理由的情况下使您的结构过于复杂。 (当然在我看来)

    【讨论】:

      【解决方案3】:

      您可以在 Building 类中使用 [NotMapped] 属性标记 Location 属性。

      using System.ComponentModel.DataAnnotations.Schema;
      public class Building
      {
          [NotMapped]
          public Location Location { get; private set; }
      }
      

      希望能解决您的问题!

      【讨论】:

      • 我认为这不是他想要的。这不会保存他想要做的实体的位置。
      • 确实,这并不能解决问题。我希望在 Building-table 内的 Location 引用国家表。我需要它映射
      • 在这种情况下,我认为您必须将“位置”映射到与建筑物和国家/地区表相关的表。
      • 嗯,我想避免这种情况。我的数据库结构不应该依赖于我的域模型。位置数据只属于建筑物,不应在单独的表中。
      猜你喜欢
      • 2020-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多