我正在尝试使用Entity Framework 5进行多对多关系的简单插入。
我有两个POCO课程如下。
public class Category
{
public virtual string Title { get; set; }
public virtual DateTime EntryDate { get; set; }
public virtual DateTime LastUpdated { get; set; }
public virtual ICollection<Article> Articles { get; set; }
}
public class Article
{
public virtual string Title { get; set; }
public virtual string Content { get; set; }
public virtual DateTime EntryDate { get; set; }
public virtual DateTime LastUpdated { get; set; }
public virtual ICollection<Category> Categories { get; set; }
}
以下流畅的api映射代码......
public class CategoryMap : EntityTypeConfiguration<Category>
{
public CategoryMap()
{
this.ToTable("Categories");
this.HasKey(x => x.ID);
this.Property(x => x.Title).IsRequired().HasMaxLength(255);
}
}
public class ArticleMap : EntityTypeConfiguration<Article>
{
public ArticleMap()
{
this.ToTable("Articles");
this.HasKey(x => x.ID);
this.HasMany(x => x.Categories)
.WithMany(x => x.Articles)
.Map(x =>
{
x.ToTable("MapArticleCats");
x.MapLeftKey("CategoryID");
x.MapRightKey("ArticleID");
});
this.Property(x => x.Title).IsRequired().HasMaxLength(255);
this.Property(x => x.Content).IsRequired().HasMaxLength(4000);
}
}
然后,实体框架将生成Category和Article表以及第三个映射表,其中详细信息在ArticleMap代码(MapArticleCats)中指定,在SQL Server中如下所示。
ArticleID - int
CategoryID -int
以下代码(给出或采取几行)将类别添加到我的控制器中的文章。
IEnumerable<Category> GetCats = CategoryRepository.GetAll();
//DO SOME CODE TO FIGURE WHICH CATEGORIES I NEED.
IEnumerable<Category> Categories = InferCategoriesFromPostedData(Model.Categories, GetCats);
foreach (Category c in Categories)
{
Article.Categories.Add(c);
}
这似乎在插入时会产生一些奇怪的行为。它会在类别表(DUPLICATE)中插入一个新类别,并将新创建的CategoryID(而不是原始ID)和正确的ArticleID插入MapArticleCats表。
谁能看到我出错的地方?
答案 0 :(得分:4)
确定在提交本文之前我应该做的事情(以及之前的那些......非常有罪)是搜索StackOverflow并且更加彻底。
我找到了问题的答案here
发生的事情与上述代码完全无关。这是因为我基本上将两个数据上下文注入我的控制器(一个在文章存储库中,另一个在类别存储库中),因此创建了重复的记录。
<强> ============================================ ====================================== 强>
重要编辑
的 =============================================== =================================== 强>
只是详细说明我的答案......
即使在完成上述修复之后,这仍然无法解决我无法更新导航属性(类别)的原始问题。对此的修复程序如下所示......
我是使用AsNoTracking()绑定实体(文章)的模型,如果您只想更新主实体本身但是您无法对导航属性执行任何操作,则可以。例如在我的案例中添加/删除文章中的类别。
这让我有点蠢蠢,因为我通过从上下文中分离实体尝试了类似的方法,但这两种方式最终给我带来了无法操纵导航属性的同样问题。
解决这个问题的方法只是简单地模拟绑定/选择实体。没有AsNoTracking(),没有分离。当将实体附加回上下文时,请使用以下代码...
public bool Attach(T entity)
{
T original = _dbSet.Find(entity.ID);
_dbContext.Entry(original).CurrentValues.SetValues(entity);
_dbContext.Entry(original).State = EntityState.Modified;
return this.Commit();
}
这样你就可以在不做任何AsNoTracking / Detaching垃圾的情况下选择它,它会更新得很好。这对我来说没问题,有些人可能会发现额外的数据库攻击有点令人反感,但是为了所有那些适合我的悲伤就好了。
答案 1 :(得分:0)
在dbcontext CaveChanges中调用:
ChangeTracker.DetectChanges()
If ChangeTracker.HasChanges Then
ChangeTracker.DetectChanges()
End If
这适合我。
答案 2 :(得分:0)
我的问题是我试图将新实例设置为导航属性。
我在做:
IList<Category> categories = _categoryService.GetSomeCategories();
article.Categories = categories;
_articleService.UpdateArticle(article);
相反,你应该坚持现有的ICollection实例,如下所示:
IList<Category> categories = _categoryService.GetSomeCategories();
article.Categories.Clear();
foreach (var category in categories) {
article.Categories.Add(category);
}
_articleService.UpdateArticle(article);
重复的PRIMARY KEY错误消失了。