实体框架 - 多对多关系插入重复到父表

问题描述 投票:3回答:3

我正在尝试使用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表。

谁能看到我出错的地方?

asp.net-mvc entity-framework-5
3个回答
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垃圾,它会更新就好了。这对我来说没问题,有些人可能会发现额外的数据库攻击有点令人反感,但为了所有那些适合我的悲伤就好了。


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错误消失了。


0
投票

在dbcontext CaveChanges调用中:

ChangeTracker.DetectChanges()

If ChangeTracker.HasChanges Then
    ChangeTracker.DetectChanges()
End If

这适合我。

© www.soinside.com 2019 - 2024. All rights reserved.