我正在开发我的第一个实体框架应用程序.我正在使用EF vesion 6(来自Nuget)和.net 4.0.但是,对我来说,我遇到了一些困难,对我来说,它看起来应该非常简单.我在互联网上发现了许多相互矛盾的建议和解决方案,但在花了几天时间尝试解决问题之后,我真的很困惑,并且质疑我对实体框架的一些基本理解.我想要做的是:创建一个简单的相关实体集合,并在从父项中删除它们时自动删除它们.
以下是我在vanilla C#中对此进行建模的方法.与Microsoft示例一致,假设我们有两个类,Post和Tag,如下所示:
public class Post { public string Name { get; set; } public string Author { get; set; } public ICollectionTags { get; set; } } public class Tag { public string Text { get; set; } // Possibly other properties here }
然后,添加标签非常简单myPost.Tags.Add(myTag)
,删除标签就像这样简单myPost.Tags.Remove(myTag)
.
现在进入实体框架的一面:我看了一下,然后想到了"外键,当然!" 但是我添加了一个FK有很多问题:标签在从帖子中删除时不会从数据库中删除,从数据库myPost.Tags
加载时会有0个元素,尽管SQL资源管理器显示PostId值是正确的,等等我对一堆技巧感到困惑,比如标记Tag.PostId
为一个键,手动删除标签,实际上将标签作为DbSet添加到上下文中,手动设置myTag.Post = null;
(我尝试使用Lazy加载启用和禁用,为了它的价值 - 虽然如果可能,我想保持关闭)
现在(在很大程度上要归功于看似矛盾和过于复杂的例子),我很困惑和迷失.有人能告诉我我应该如何在EF中建立这种关系吗?(顺便说一下,我正在使用Code First)
解:感谢Moho,我想出了这个结构,它完全符合我的要求:
public class Post { public int Id { get; set; } public string Name { get; set; } public string Author { get; set; } public virtual ICollectionTags { get; set; } public Post() { Tags = new HashSet (); } } public class Tag { [Key, Column(Order=1), DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } public string Text { get; set; } // Possibly other properties here public virtual Post Post { get; set; } [Key, Column(Order=2)] public virtual int PostId { get; set; } } public class TestContext : DbContext { public DbSet Posts { get; set; } }
当Tag
从Post
标签集合中删除a时,实体框架将为标签发出DELETE,如此处所述(#2):http://www.kianryan.co.uk/2013/03/orphaned-child/
同样,向帖子添加标签将自动发出INSERT并设置FK关系.
有一点需要注意:确保使用virtual
!我认为这也是我很多挫败感的根源.