加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 如何定义EF代码优先的三向FK关系? (有两个相关孩子的父母

发布时间:2020-12-15 17:24:06 所属栏目:百科 来源:网络整理
导读:我不确定如何准确地表达我的问题,所以我将深入研究我所做的事情并描述问题.实际问题是在帖子的最后. 我使用EF 4.3代码优先,并有这个通用的Category实体来组织各种类型的内容: public enum ContentType { Articles,Videos };public class Category{ public l
我不确定如何准确地表达我的问题,所以我将深入研究我所做的事情并描述问题.实际问题是在帖子的最后.

我使用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表.

下一步是为Video添加一个类似的实体和映射定义,它也按预期工作.

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(必需:可选)引用.

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不应该是可空的,与图像相反):

如何使用代码优先的流利表示法定义这种关系?

解决方法

我无法重现这个问题,你的配置很好(我在这里使用自动迁移).

你可以添加它给你的确切错误吗?

无论如何,这是我的确切代码:https://gist.github.com/1961958

这就是Update-Database:https://gist.github.com/1961961生成的SQL

编辑:操作,我没有看到@BalazsTihanyi完全相同的答案,对不起.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读