简体   繁体   English

实体框架6和集合

[英]Entity Framework 6 and collections

I'm developing my first entity-framework app. 我正在开发我的第一个实体框架应用程序。 I'm using EF vesion 6 (from Nuget) and .net 4.0. 我正在使用EF vesion 6(来自Nuget)和.net 4.0。 However, I'm having some difficulty with something that, to me, seems like it should be extraordinarily simple. 但是,对我来说,我遇到了一些困难,对我来说,它似乎应该非常简单。 I've found lots of conflicting advice and solutions on the internet, but after spending several days trying to work things out, I'm really confused and am to the point of questioning some basic understandings I have of the Entity Framework. 我在互联网上发现了许多相互矛盾的建议和解决方案,但在花了几天时间尝试解决问题之后,我真的很困惑,并且质疑我对实体框架的一些基本理解。 What I want to do is this: create a simple collection of related entities, and automatically delete them when they're removed from the parent. 我想要做的是: 创建一个简单的相关实体集合,并在从父项中删除它们时自动删除它们。

Here's how I would model this in vanilla C#. 以下是我在vanilla C#中对此进行建模的方法。 In keeping with Microsoft samples, assume we have two classes, Post and Tag, like so: 与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
}

Then, adding a tag is as simple as myPost.Tags.Add(myTag) and removing a tag is as simple as myPost.Tags.Remove(myTag) . 然后,添加标签就像myPost.Tags.Add(myTag)一样简单,删除标签就像myPost.Tags.Remove(myTag)一样简单。

Now to the Entity Framework side of things: I looked at that and thought "Foreign Key, of course!" 现在进入实体框架的一面:我看了一下,然后想到了“外键,当然!” but I had a host of issues adding a FK: Tags wouldn't delete from the database when they were removed from the post, myPost.Tags would have 0 elements when loaded from the db, despite the SQL explorer showing that the PostId value was correct, etc. I faffled around with a bunch of tricks, like marking the Tag.PostId as a Key, manually removing Tags, actually adding Tag to the context as a DbSet, manually setting myTag.Post = null; 但是我添加了一个FK有很多问题:标签在从帖子中删除时不会从数据库中删除, myPost.Tags从db加载时会有0个元素,尽管SQL资源管理器显示PostId值是我纠结于一堆技巧,比如将Tag.PostId标记为Key,手动删除Tag,实际上将Tag添加到上下文作为DbSet,手动设置myTag.Post = null; (I tried with Lazy loading both enabled and disabled, for what it's worth - though I'd like to keep it off if possible) (我尝试使用Lazy加载启用和禁用,以及它的价值 - 尽管如果可能的话我想保持关闭)

Now (thanks in no small part to seemingly conflicted and overly-complicated examples), I'm quite confused and lost. 现在(在很大程度上要归功于看似矛盾和过于复杂的例子),我很困惑和迷失。 Can someone tell me exactly how I should go about setting this relationship up in EF? 有人能告诉我我应该如何在EF中建立这种关系吗? (I'm using Code First, by the way) (顺便说一下,我正在使用Code First)

SOLUTION: 解:

Thanks to Moho, I've come up with this structure, which does exactly what I want: 感谢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 is removed from a Post 's Tags collection, Entity Framework will issue a DELETE for the tag, as outlined here (#2): http://www.kianryan.co.uk/2013/03/orphaned-child/ Tag从删除Post的标签集合,实体框架将发出对标签的删除,因为这里概述(#2): http://www.kianryan.co.uk/2013/03/orphaned-child /

Likewise, adding a tag to a post will automatically issue an INSERT and set the FK relationship. 同样,向帖子添加标签将自动发出INSERT并设置FK关系。

One thing to note: Make sure you use virtual ! 有一点需要注意:确保使用virtual I think that was the root of a lot of my frustration as well. 我认为这也是我很多挫败感的根源。

Try also defining the relationship from the Tag side as well, specifying each Tag relates to a single Post and is required. 尝试同样定义Tag侧的关系,指定每个Tag与单个Post并且是必需的。

Add a required navigation property to Post in Tag : 将所需的导航属性添加到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; }
}

Alternatively, if you really don't want to add the navigation property, you can use the Fluent API: 或者,如果您确实不想添加导航属性,则可以使用Fluent API:

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

This is probably thread necromancy, but I don't have the rep to just comment. 这可能是线程死灵,但我没有代表评论。 Wouldn't the following do what you need? 以下不会做你需要的吗?

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 is loaded from the database, then used as the Foreign Key (via the annotation) into the Post class. PostId从数据库加载,然后用作外键(通过注释)进入Post类。 Post is virtual, nothing else is. 帖子是虚拟的,没有别的。 You could probably just go with the basic [Key] annotation too. 您也许可以使用基本的[Key]注释。

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

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