我不确定如何准确地表达我的问题,所以我将深入研究我所做的事情并描述问题。实际问题在帖子的末尾。
我使用的是带有代码优先的EF 4.3,并且有一个通用的Category实体来组织各种类型的内容:
public enum ContentType { Articles, Videos };
public class Category
{
public long ID { get; set; }
public long? ParentCategoryID { get; set; }
internal int ContentTypeValue { get; set; }
public string Title { get; set; }
public virtual Category ParentCategory { get; set; }
public virtual ICollection<Category> ChildCategories { get; set; }
public ContentType ContentType
{
get { return (ContentType) ContentTypeValue; }
set { ContentTypeValue = (int) value; }
}
}
使用以下定义将其映射到数据库(我使用的是辅助类,但Map只是指实体的具体模型构建器):
Map.Property( e => e.ContentTypeValue ).IsRequired().HasColumnName( "ContentType" );
Map.Property( e => e.Title ).IsRequired().HasMaxLength( 200 );
Map.HasOptional( e => e.ParentCategory ).WithMany( r => r.ChildCategories ).HasForeignKey( e => e.ParentCategoryID ).WillCascadeOnDelete( false );
请注意,Category不提供对其他实体类型的引用(自身除外)。
然后我添加了一个Article实体及其映射:
public class Article
{
public long ID { get; set; }
public long CategoryID { get; set; }
public string Title { get; set; }
public string Body { get; set; }
public virtual Category Category { get; set; }
}
Map.Property( e => e.Title ).IsRequired().HasMaxLength( 50 );
Map.Property( e => e.Body ).IsRequired().HasMaxLength( 4000 );
Map.HasRequired( e => e.Category ).WithMany().HasForeignKey( e => e.CategoryID ).WillCascadeOnDelete( false );
这样可以正常工作,并创建一个带有PK(ID)和FK(CategoryID)的Article表到Category表。
下一步是为视频添加一个类似的实体和映射定义,它也按预期工作。
public class Video
{
public long ID { get; set; }
public long CategoryID { get; set; }
public string Title { get; set; }
public string FileName { get; set; }
public virtual Category Category { get; set; }
}
Map.Property( e => e.Title ).IsRequired().HasMaxLength( 50 );
Map.Property( e => e.FileName ).IsRequired().HasMaxLength( 200 );
Map.HasRequired( e => e.Category ).WithMany().HasForeignKey( e => e.CategoryID ).WillCascadeOnDelete( false );
但是,现在我希望Article能够直接引用特定的视频(无论它们属于哪个类别),所以本质上是两者之间的1:1(必需:可选)引用。 / p>
public class Article // broken
{
public long ID { get; set; }
public long CategoryID { get; set; }
public long? VideoID { get; set; }
public string Title { get; set; }
public string Body { get; set; }
public virtual Category Category { get; set; }
public virtual Video Video { get; set; }
}
为了映射课程,我将使用以下内容:
Map.Property( e => e.Title ).IsRequired().HasMaxLength( 50 );
Map.Property( e => e.Body ).IsRequired().HasMaxLength( 4000 );
Map.HasRequired( e => e.Category ).WithMany().HasForeignKey( e => e.CategoryID ).WillCascadeOnDelete( false );
Map.HasOptional( e => e.Video ).WithMany().HasForeignKey( e => e.VideoID ).WillCascadeOnDelete( false );
一旦我添加了这样的引用,EF就无法使用DbUpdateException创建数据库模式,其错误消息是“无法确定(约束名称)的主要结束”。多个添加的实体可能具有相同的主键。“
我可以通过没有视频参考类别(或没有文章参考视频,如在所示的第一个代码中)解决问题,但这将破坏类类的通用目的并迫使我维护ArticleCategories,VideoCategories等等。
要完全清楚我需要什么,这里是我想要最终的架构(注意:视频中的CategoryID不应该是可空的,与图像相反):
如何使用代码优先的流畅表示法定义这种关系?
答案 0 :(得分:1)
奇怪,但这对我有用。我无法从您提交的代码中重现错误 如果您尝试从迁移0重新创建表,该怎么办?
答案 1 :(得分:1)
我无法重现此问题,您的配置很好(我在这里使用自动迁移)。
你可以添加它给你的确切错误吗?
无论如何,这是我的确切代码:https://gist.github.com/1961958
这是来自Update-Database的生成的SQL:https://gist.github.com/1961961
编辑:操作,我没有看到@BalazsTihanyi完全相同的答案,抱歉。