如何映射具有对实体的引用的值类型?

时间:2013-06-24 12:03:19

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

我在实体框架中遇到问题。

我有以下课程(简化):

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相同的表。

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

我见过一些解决方法,说你需要将Country放在Building-class上,但这感觉不好(并且在语义上是完全错误的)。

我正在使用Entity Framework 5

3 个答案:

答案 0 :(得分: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表的外键。

我知道您发布问题已经很久了,但是我认为此答案可能会对遇到此问题的人有所帮助。

答案 1 :(得分:0)

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

我知道您不会将位置视为实体,但添加实体对复杂类型的引用似乎也不是一个可靠的方法。建筑物与国家的关系非常直接。建筑物属于一个国家。因此,建筑模型应包括国家ID。你期望映射什么?

如果您希望表格Building只有三列ID, Street, CountryId而您仍想保留位置模型,则应使用以下复杂类型。

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

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

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

答案 2 :(得分:-3)

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

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

希望能解决你的问题!