【问题标题】:Entity Framework - Many To Many Relationship Inserting Duplicate To Parent Table实体框架 - 向父表插入重复的多对多关系
【发布时间】:2012-11-05 11:12:48
【问题描述】:

我正在尝试使用 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 - 整数
类别ID -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


    【解决方案1】:

    好吧,在提交这篇文章(以及以前的文章......非常有罪)之前我应该​​做的是搜索 StackOverflow 并更彻底地搜索。

    我找到了问题的答案here

    发生的事情与上面的代码完全无关。这是因为我实际上将两个数据上下文注入到我的控制器中(一个在文章存储库中,另一个在类别存储库中),因此创建了重复记录。

    ============================================== =======================================
    重要编辑
    ========================================= ===========================================

    只是为了详细说明我的答案...

    即使进行了上述修复,这仍然没有解决我无法更新导航属性(类别)的原始问题。解决方法如下...

    我使用 AsNoTracking() 对实体 (Article) 进行模型绑定,如果您只想更新主实体本身但无法对导航属性执行任何操作,则可以这样做。例如在我的情况下,从文章中添加/删除类别。

    这让我有点不知所措,因为我尝试了一种类似的方法,将实体从上下文中分离出来,但两种方法最终都给我带来了同样的问题,即无法操作导航属性。

    解决这个问题的方法就是像平常一样简单地建模绑定/选择实体。没有 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 垃圾的情况下将其选中,并且它会更新得很好。这对我来说没问题,有些人可能会觉得额外的 db 之旅有点冒犯,但为了所有适合我的悲伤就好了。

    【讨论】:

      【解决方案2】:

      我的问题是我试图为导航属性设置新实例。

      我在做:

      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);
      

      重复的主键错误消失了。

      【讨论】:

        【解决方案3】:

        在您的 dbcontext CaveChanges 调用中:

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

        这对我有用。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-08-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多