我正在开发我的第一个实体框架应用程序。我正在使用 EF 版本 6(来自 Nuget)和 .net 4.0。然而,我在一些对我来说似乎应该非常简单的事情上遇到了一些困难。我在互联网上发现了很多相互矛盾的建议和解决方案,但是在花了几天时间尝试解决问题之后,我真的很困惑,并且质疑我对实体框架的一些基本理解。我想做的是这样的:创建相关实体的简单集合,并在从父级中删除它们时自动删除它们。
以下是我在普通 C# 中对此进行建模的方法。为了与 Microsoft 示例保持一致,假设我们有两个类:Post 和 Tag,如下所示:
public class Post
{
public string Name { get; set; }
public string Author { get; set; }
public ICollection<Tag> Tags { 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
作为Key,手动删除Tags,实际上将Tag作为DbSet添加到上下文中,手动设置myTag.Post = null;
(我尝试启用和禁用延迟加载,因为它是值得的 - 尽管我想如果可能的话将其关闭)
现在(在很大程度上要归功于看似冲突和过于复杂的例子),我非常困惑和迷失。有人能准确地告诉我应该如何在 EF 中建立这种关系吗? (顺便说一句,我正在使用 Code First)
解决方案:
感谢 Moho,我想出了这个结构,它正是我想要的:
public class Post
{
public int Id { get; set; }
public string Name { get; set; }
public string Author { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
public Post()
{
Tags = new HashSet<Tag>();
}
}
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<Post> Posts { get; set; }
}
When a Tag
被从a中删除Post
的标签集合,实体框架将为该标签发出 DELETE,如此处所述 (#2):http://www.kianryan.co.uk/2013/03/orphaned-child/ http://www.kianryan.co.uk/2013/03/orphaned-child/
同样,向帖子添加标签将自动发出 INSERT 并设置 FK 关系。
需要注意的一件事:确保你使用virtual
!我认为这也是我很多挫败感的根源。