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

问题描述 投票:13回答:3

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

我有以下课程(简化):

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是实体,它们保存在数据库中。位置是值类型,应映射到与Building相同的表。

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

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

我正在使用Entity Framework 5

c# .net entity-framework entity-framework-5
3个回答
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表的外键。

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


0
投票

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

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

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

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

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

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


-3
投票

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

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

希望能解决你的问题!

© www.soinside.com 2019 - 2024. All rights reserved.