c# - Entity Framework 6 和集合

标签 c# entity-framework

我正在开发我的第一个 Entity Framework 应用程序。我正在使用 EF vesion 6(来自 Nuget)和 .net 4.0。但是,我在处理一些对我来说似乎应该非常简单的事情时遇到了一些困难。我在 Internet 上发现了很多相互矛盾的建议和解决方案,但在花了几天时间尝试解决问题之后,我真的很困惑,以至于质疑我对 Entity Framework 的一些基本理解。我想要做的是:创建一个简单的相关实体集合,并在它们从父实体中移除时自动删除它们。

下面是我将如何在普通 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) 一样简单.

现在是 Entity Framework 方面的事情:我看着它并想“当然是外键!”但是我在添加 FK 时遇到了很多问题:标签在从帖子中删除时不会从数据库中删除,myPost.Tags 从数据库加载时会有 0 个元素,尽管有 SQL资源管理器显示 PostId 值是正确的,等等。我用了很多技巧,比如将 Tag.PostId 标记为键,手动删除标签,实际上将标签作为 DbSet 添加到上下文中,手动设置 myTag.Post = null;(我尝试启用和禁用延迟加载,因为它的值(value) - 尽管我希望尽可能将其关闭)

现在(在很大程度上要归功于看似矛盾和过于复杂的示例),我感到非常困惑和迷茫。有人能确切地告诉我应该如何在 EF 中建立这种关系吗? (顺便说一句,我正在使用代码优先)

解决方案:

感谢 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; }
}

TagPost 的 Tags 集合中删除时,Entity Framework 将为该标签发出 DELETE,如此处所述(#2):http://www.kianryan.co.uk/2013/03/orphaned-child/

同样,给帖子添加标签会自动发出 INSERT 并设置 FK 关系。

需要注意的一件事:确保使用virtual!我认为这也是我很多挫败感的根源。

最佳答案

也尝试从 Tag 端定义关系,指定每个 Tag 与单个 Post 相关并且是必需的。

Tag 中向 Post 添加一个必需的导航属性:

public class Tag
{
    // you need an ID
    public int Id { get; set; }

    public string Text { get; set; }

    [Required]
    public virtual Post Post { get; set; }
}

或者,如果您真的不想添加导航属性,您可以使用 Fluent API:

modelBuilder.Entity<Post>().HasMany( p => p.Tags ).WithRequired();

关于c# - Entity Framework 6 和集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20625991/

相关文章:

c# - 是否可以返回异常?

c# - stream.CopyTo - 文件为空。网站

c# - 配置多个数据库 Entity Framework 6

c# - 无法加载文件或程序集 'EntityFramework' 或其依赖项之一

sql-server - 更改关系的默认名称

sql - 返回包含博客文本的整个表而不是选择特定列的性能

c# - 第一次异常 - System.pdb 未加载

c# - Dapper 示例代码的说明

c# - EF Core 如何通过另一个列表过滤嵌套的多对多列表

entity-framework - Entity Framework 7 Include() 未按预期工作