Entity Framework 中的多对多关系 - 导致“实体对象不能被 IEntityChangeTracker 的多个实例引用”

Many to many relationship in Entity Framework - results in “An entity object cannot be referenced by multiple instances of IEntityChangeTracker”

我正在尝试在 Entity Framework 中设置一个经典的 "Article and Categories" 场景。为此,我有这些 类:

public class RichContent : BaseIdEntity
{
    public string Headline { get; set; }

    public virtual List<RichContentCategory.RichContentCategory> Categories { get; set; }


    public RichContent()
    {
        Categories = new List<RichContentCategory.RichContentCategory>();
    }
}

我的类别:

public class RichContentCategory : BaseIdEntity
{
    public string Name { get; set; }
    public virtual List<RichContent.RichContent> RichContents { get; set; }

    public RichContentCategory()
    {
        this.RichContents = new List<RichContent.RichContent>();
    }
}

这是这样设置的:

   modelBuilder.Entity<RichContent>()
                   .HasMany<RichContentCategory>(s => s.Categories)
                   .WithMany(c => c.RichContents)
                   .Map(cs =>
                   {
                       cs.MapLeftKey("RichContentRefId");
                       cs.MapRightKey("RichContentCategoryId");
                       cs.ToTable("RichContentCategoryPlacement");
                   });

现在,当我 运行 添加如下类别并保存时:

   item.Categories.Add(richContentCategory);

我在 CREATE 方法中的 _db.RichContent.Add(content); 处收到以下错误:

An unhandled exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll

Additional information: An entity object cannot be referenced by multiple instances of IEntityChangeTracker.

我可以理解潜在的问题是我需要如何使用相同的上下文。但是,我使用 Ninject 注入上下文,我创建的服务如下所示:

 public class RichContentService : IRichContentService
    {
        private readonly Context _db;

        public RichContentService(Context db)
        {
            _db = db;
        }

        public RichContent Create(RichContent content)
        {
            _db.RichContent.Add(content);

            _db.SaveChanges();

            return GetById(content.Id);
        }
}

所以我的问题基本上是 - 在这种情况下如何向文章添加类别?

编辑:

我的代码 运行s 是一个进口商,有这个:

 finally
                {
                    if (needToCreate)
                    {
                        var result = Create(richContent);
                        logger.Info("Created a new rich-content page");
                    }
                }

以及 Create() 方法:

 public RichContent Create(RichContent content)
        {
            PerformValidation(content);

            _db.RichContent.Add(content);
            _db.SaveChanges();

            return GetById(content.Id);
        }

以及 CREATE 方法的输入:

 var item = new RichContent()
            {
                WordpressId = dto.id,
                DateCreated = dto.date,
                Slug = dto.slug,
                Content = dto.content,
                Headline = dto.title,
                DateModified = dto.modified,

            };

            if (dto.custom_fields.category_type != null && dto.custom_fields.category_type.Any() &&
               !string.IsNullOrEmpty(dto.custom_fields.category_type[0]))
            {
                var categories = _richContentCategoryService.GetBySpecification(new RichContentCategorySpecification()
                {
                    Take = Int32.MaxValue
                });

                var list = dto.custom_fields.category_type[0];
                foreach (var richContentCategory in categories)
                {

                    if (list.Contains(richContentCategory.WordpressName))
                    {
                        item.Categories.Add(richContentCategory);
                    }
                }
            }

            if (dto.custom_fields.featured != null)
            {
                item.Featured = dto.custom_fields.featured.Any(c => c == "1");
            }

            if (dto.custom_fields.area != null)
            {
                item.Area = dto.custom_fields.area.Any(c => c == "1");

                if (item.Area)
                {
                    var children = ConvertWordpressDtos(dto.children);
                    foreach (var child in children.Where(c=>c.Area))
                    {

                        child.Slug = string.Format("{0}/{1}", item.Slug, child.Slug);
                        item.Children.Add(child);
                    }
                }


            }

问题

异常清楚地表明,当您保存新的 RichContent 时,与 RichContent 关联的实体被另一个 Entity Framework 上下文跟踪。在您的特定情况下,实体是从 _richContentCategoryService.GetBySpecification:

返回的 RichContentCategory
var categories = _richContentCategoryService.GetBySpecification(new RichContentCategorySpecification()
{
    Take = Int32.MaxValue
});

var list = dto.custom_fields.category_type[0];
foreach (var richContentCategory in categories)
{
    if (list.Contains(richContentCategory.WordpressName))
    {
        item.Categories.Add(richContentCategory);
    }
}

如何修复

此处最好的选择是设法为该场景中使用的所有对象使用相同的上下文。为此,您可以将 item 添加到类别,然后使用 _richContentCategoryService 保存类别:

var categories = _richContentCategoryService.GetBySpecification(new RichContentCategorySpecification()
{
    Take = Int32.MaxValue
});

var list = dto.custom_fields.category_type[0];
foreach (var richContentCategory in categories)
{
    if (list.Contains(richContentCategory.WordpressName))
    {
        richContentCategory.RichContents.Add(item);
    }
}

// Save updated categories somehow, using "_richContentCategoryService" object
_richContentCategoryService.Save(categories);

如果你做不到,你可以尝试这样做:

foreach (var richContentCategory in categories)
{
    if (list.Contains(richContentCategory.WordpressName))
    {
        item.Categories.Add(new RichContentCategory { Id = richContentCategory.Id});
    }
}