繁体   English   中英

实体框架6和集合

[英]Entity Framework 6 and collections

我正在开发我的第一个实体框架应用程序。 我正在使用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 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从db加载时会有0个元素,尽管SQL资源管理器显示PostId值是我纠结于一堆技巧,比如将Tag.PostId标记为Key,手动删除Tag,实际上将Tag添加到上下文作为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 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; }
}

Tag从删除Post的标签集合,实体框架将发出对标签的删除,因为这里概述(#2): http://www.kianryan.co.uk/2013/03/orphaned-child /

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

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

尝试同样定义Tag侧的关系,指定每个Tag与单个Post并且是必需的。

将所需的导航属性添加到Post in Tag

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();

这可能是线程死灵,但我没有代表评论。 以下不会做你需要的吗?

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 int PostId { get; set; }

    [ForeignKey("PostId")]
    public virtual Post Post { get; set; }

}

PostId从数据库加载,然后用作外键(通过注释)进入Post类。 帖子是虚拟的,没有别的。 您也许可以使用基本的[Key]注释。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM