简体   繁体   English

EF 6.0多对多关系编辑

[英]EF 6.0 Many to Many Relationships edits

I'm having a problem with my Entity Framework 6.0 my set up is as follows 我的Entity Framework 6.0存在问题,我的设置如下

public Post
{
    [Key]
    public int Id {get;set;}

    public String Name {get;set;}

    public virtual List<Category> Categories {get;set;}
}

public Category
{
    [Key]
    public int Id {get;set;}

    public string Name {get;set;}

    public virtual List<Post> Posts {get;set;}
}

so the problem arises when I try to modify one of the lists like this 所以当我尝试修改这样的列表之一时会出现问题

Posts.Categories.Remove(category);
Posts.Categories.Add(newCategory);
entities.SaveChanges();

I get the following exception, and the exception only happens when I try to modify a Post that has already been created and that has categories . 我得到以下异常,只有在我尝试修改已创建且具有类别帖子时才会发生异常。

If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted. 如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。

I'm not too sure what to do in this case, should I delete the Post from the Category as well ??? 我不太确定在这种情况下该怎么做,我应该从类别中删除帖子吗? Keep in mind that by removing the Category from the list I just want to remove it from that collection not to remove the whole object from my DB. 请记住,通过从列表中删除类别 ,我只想从该集合中删除它,而不是从我的数据库中删除整个对象。 Any suggestions ? 有什么建议么 ?

This is my first post to StackOverflow if somebody needs more info please let me know. 这是我给StackOverflow的第一篇文章,如果有人需要更多信息请告诉我。

The way I handle these many to many relationships is as follows: (assuming Post is an object from the DB) 我处理这些多对多关系的方式如下:(假设Post是来自DB的对象)

            var tmp = Post.Categories.Select(q => q).ToList();
            //delete all links
            foreach (var lab in tmp) {
                Posts.Categories.Remove(lab);
            }
            db.SaveChanges();

            //add new cats
            foreach (var lblgroup in myListofNewCats) {
               Post.Categories.Add(db.Categories.Single(q => q.ID=something);                    
            }

It works out best when you submit your changes after the delete. 删除后提交更改时效果最佳。 In case there are no changes, or in case you remove and add the same entity again without submitting in between it might throw some errors. 如果没有更改,或者如果您再次删除并添加相同的实体而不在其间提交,则可能会引发一些错误。

I'm sure there might be better solutions. 我相信可能有更好的解决方案。

You could define your middle table and then just delete the record in that. 您可以定义中间表,然后只删除其中的记录。 That way, you would not be deleting the category itself, which it appears that you are doing now. 这样,你就不会删除你自己现在正在做的类别本身。 I suggest that you amend your models as follows: 我建议您修改模型如下:

public Post
{
    [Key]
    public int Id {get;set;}

    public String Name {get;set;}

    //For the many to 1 relationship
    public virtual ICollection <PostCategory> PostCategories{get;set;}

    //You wont need this anymore
    //public virtual List<Category> Categories {get;set;}
}

and... 和...

public Category
{
    [Key]
    public int Id {get;set;}

    public string Name {get;set;}

    //For the many to 1 relationship
    public virtual ICollection <PostCategory> PostCategories{get;set;}

    //You wont need this anymore
    //public virtual List<Post> Posts {get;set;}
}

Now create model for the new table, PostCategory, this will be the middle table. 现在为新表创建模型,PostCategory,这将是中间表。 I like to use a single key rather than a double key. 我喜欢使用单个键而不是双键。 You get more flexibility and it is easy to use when using repositories and the out of the box controller delete methods, but you can use a double key if you like - I am not showing that here. 您可以获得更大的灵活性,并且在使用存储库和开箱即用的控制器删除方法时很容易使用,但如果您愿意,可以使用双键 - 我没有在此处显示。 In this method, you will need to check for duplicates yourself before adding the record to the database. 在此方法中,您需要在将记录添加到数据库之前自行检查重复项。

public PostCategory 
{
    [Key]
    public int Id {get;set;}  
    public int PostId {get;set;}
    public virtual Post Post {get;set;}

    public int CategoryId {get;set;}
    public virtual Category Category {get;set;}
}

Remember to define "PostCategories" in your dbcontext as well. 请记住在dbcontext中定义“PostCategories”。 (I presume you know how to...?) (我猜你知道怎么......?)

Now when you want to delete the link between the Post and the Category, just delete the PostCategory record, like this in your controller: 现在,当您想要删除帖子和类别之间的链接时,只需在控制器中删除PostCategory记录,如下所示:

//Find the record where postId is the PostId and the categoryId is the CategoryId
var postRecord = db.PostCategories.FirstOrDefault(x=>x.PostId==postId && x.CategoryId==categoryId);

if(postRecord!=null)
{
   db.PostCategories.Remove(postRecord)
   db.SaveChanges();
}

Adding a record is also easy. 添加记录也很容易。 I do it like this in the controller... 我在控制器中这样做...

//First create a record to add
PostCategory pc= new PostCategory()

//wire it up... EF adds the Id fields into the record. If you have a problem
// you can even add those.
pc.Category = category;
pc.Post = post;

//add it
db.PostCategories.Add(pc);
db.SaveChanges();

I like this method because now you can save additional stuff in your PostCategory table, such as date of Post etc. I don't like Many to Many relationships, I believe that they will sooner or later be broken down to one to many and many to one... and later when you have to "fix code" - its a pain to say the least. 我喜欢这种方法,因为现在你可以在你的PostCategory表中保存额外的东西,例如Post等日期。我不喜欢很多很多关系,我相信它们迟早会分解为一对多和很多一个......以及后来当你必须“修改代码”时 - 至少可以说是痛苦。 I hope this helps. 我希望这有帮助。

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

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