EF 6.0 多对多关系编辑
本文关键字:关系 编辑 EF | 更新日期: 2023-09-27 18:31:52
我的实体框架 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;}
}
所以当我尝试像这样修改其中一个列表时会出现问题
Posts.Categories.Remove(category);
Posts.Categories.Add(newCategory);
entities.SaveChanges();
我收到以下异常,并且仅当我尝试修改已创建且具有类别的帖子时,才会发生异常。
如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。
我不太确定在这种情况下该怎么办,我是否也应该从类别中删除帖子???请记住,通过从列表中删除类别,我只想将其从该集合中删除,而不是从我的数据库中删除整个对象。有什么建议吗?
这是我在StackOverflow上的第一篇文章,如果有人需要更多信息,请告诉我。
我处理这些多对多关系的方式如下:(假设 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);
}
当您在删除后提交更改时,效果最佳。如果没有更改,或者如果您删除并再次添加同一实体而不在两者之间提交,则可能会引发一些错误。
我相信可能会有更好的解决方案。
您可以定义中间表,然后删除其中的记录。这样,您就不会删除类别本身,您现在似乎正在这样做。我建议您按以下方式修改模型:
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;}
}
和。。。
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;}
}
现在为新表创建模型,PostCategory,这将是中间的表。我喜欢使用单键而不是双键。在使用存储库和开箱即用的控制器删除方法时,您可以获得更大的灵活性并且易于使用,但如果您愿意,您可以使用双键 - 我在这里不展示。在此方法中,您需要在将记录添加到数据库之前自己检查重复项。
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;}
}
请记住在数据库上下文中定义"PostCategories"。(我想你知道怎么做...?
现在,当您要删除帖子和类别之间的链接时,只需删除帖子类别记录,就像控制器中的这样:
//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();
}
添加记录也很容易。我在控制器中这样做...
//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();
我喜欢这种方法,因为现在您可以在PostCategory表中保存其他内容,例如发布日期等。我不喜欢多对多的关系,我相信它们迟早会被分解成一对多,多对一......后来当你必须"修复代码"时 - 至少可以说这是一种痛苦。我希望这有所帮助。