我已经在这个主题上阅读了尽可能多的帖子,但我尝试过的解决方案似乎都没有。我有一个现有的数据库,并创建了一个新的Code First From Existing Database项目。
我有一个名为Thing的基表。每个对象在此表中都有一条记录,使用Id作为唯一主键。每个其他对象都继承自此,但它们在子表中使用相同的Id,而不在子表中使用新的Identity列。有效地给每个'Thing'一个唯一的ID:
public class Thing
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Car
{
public int Id { get; set; }
//other properties
}
public class Person
{
public int Id { get; set; }
//other properties
}
public class Color
{
public int Id { get; set; }
//other properties
}
每个新记录首先在'Thing'中创建一个项目,然后使用该Id值在其各自的表中创建一个新记录,创建多个1到0..1关系,其中派生表上的Id字段也是FK到了事。
东西1到0..1车
事情1到0..1人
东西1到0..1颜色
等等
我尝试了许多不同的Data Annotation和Fluent API组合,但它总是会回到同样的错误:
'无法检索Model.Car的元数据'。无法确定类型'Model.Thing'和'Model.Car'之间的主要关联结束。必须使用关系流畅API或数据注释显式配置此关联的主要结尾。'
我确实设法通过使用带有反向注释的虚拟并将Id字段设置为Key和ForeignKey来解决此错误,但随后消息跳转到Person。如果您将其设置为与Car相同,则消息将恢复为Car。
似乎我可以回去为每个子表创建一个正常的外键,但这是很多工作,我相信有可能以某种方式使这个工作。最好使用流畅的API。
答案 0 :(得分:0)
如果您要使用数据注释,您还需要将依赖实体的PK声明为FK:
public class Thing
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Car Car{get;set;}
}
public class Car
{
[Key,ForeignKey("Thing")]
public int ThingId { get; set; }
//other properties
public virtual Thing Thing{get;set;}
}
如果您打算使用Fluent Api(从模型中删除属性),配置将如下所示:
modelBuilder.Entity<Car>().HasRequired(c=>c.Thing).WithOptional(t=>t.Thing);
根据指定的多重性,只有Thing
成为主体且Car
成为依赖,才有意义,因为Thing
可以在没有{{1}的情况下存在但是Car
必须有Car
。
正如您所看到的,您不需要指定Thing
是此关系的FK。这是因为Entity Framework要求将依赖项的主键用作外键。由于没有选择,Code First会为您推断出这一点。
再次阅读您的问题我认为您正在尝试创建层次结构。在这种情况下,您可以使用Table per Type (TPT)方法。