我在实体框架中遇到了映射问题。
我有以下课程(简化):
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
自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
类映射到的表的一部分。这意味着你只有Building
和Country
类的表,而Building
表将有Country
表的外键。
我知道你发布问题已经很久了,但我认为这个答案对于遇到这个问题的人可能会有所帮助。
在我看来,实体框架不应该允许这样的情况。
我知道你不认为Location是一个实体,但是添加实体引用到复杂类型似乎也不是一个可靠的方法。建筑物与国家的关系非常直接。建筑物属于一个国家。因此,建筑模型应包括国家ID。你期望映射什么?
如果您希望表格Building只有三列ID, Street, CountryId
并且您仍然想要保留Location模型,那么您应该使用以下复杂类型。
public class Location
{
public string Street {get; set;}
public int countryId {get; set}
}
但是,如果您希望您的Building表具有来自模型Country的所有字段,则可能会导致一些棘手的情况,例如会发生什么情况如果您想要向Country模型添加新字段或者如果您想添加其他复杂类型或根据新业务案例,您所在国家/地区的实体模型。
这些案例会混淆关系概念,并且会在没有任何有意义的理由的情况下使您的结构过于复杂。 (当然我认为)
您可以使用[NotMapped]属性在Building类中标记Location属性。
using System.ComponentModel.DataAnnotations.Schema;
public class Building
{
[NotMapped]
public Location Location { get; private set; }
}
希望能解决你的问题!