在断开连接的环境中插入/更新与实体框架的多对多关系

时间:2015-08-18 09:29:35

标签: c# entity-framework asp.net-web-api entity-framework-6

我有一个调用webApi的web应用程序,我的webApi调用我的服务,我的服务调用我的DbContext。

我有2个实体,内容和文件。这些是单独的实体,存储在单独的表中。

现在我还有一个针对内容的集合,名为Files。这用于将文件引用到内容实体。

实体框架因此创建了名为Content,File和ContentFile的表。我对实体框架的配置是这样的

public ContentConfig() 
    : base()
{
    this.HasMany<File>(s => s.Files)
        .WithMany(c => c.Contents)
        .Map(e =>
        {
            e.MapLeftKey("ContentId");
            e.MapRightKey("FileId");
            e.ToTable("ContentFile");
        });
}

到我的webApi,我发送内容的数据,看起来像这样

Id = 1,
Files = {
    { Id = 1, Name = "Test" }
}

这里我有一个已经存在ID为1的内容实体,以及一个已经存在ID为1的文件。我正在传递这个,因为我希望实体框架在2个实体之间建立关系。 / p>

在我的服务中,我有这段代码。

public Task<int> AddOrUpdateAsync(Content content)
{
    // attach all files
    foreach (var file in content.Files)
        _context.Entry(file).State = EntityState.Modified;

    _context.Entry(content).State = EntityState.Modified;

    return _context.SaveChangesAsync();
}

这一切似乎都是,更新我的内容实体并更新文件实体。没有关系插入?有人可以帮我插入这段关系吗?如果Update上已经存在会发生什么?实体框架会为我说出来吗?

当一切都断开连接时,似乎很难处理实体?或者这只是我?在我的单元测试中,这可以工作,但实体没有断开连接。

不确定它是否与它有关,但我使用AutoMapper从我的webApi模型创建我的实体。

1 个答案:

答案 0 :(得分:0)

当您正在断开工作时,它可能是一种解决方案,可以在您的业务方法(服务器端)中加载原始实体,并使用已连接的导航属性并稍后保存。

例如,以下代码显示了如何在断开连接的场景中保存包含子产品的类别:

protected void UpdateCategoryWithProducts(Category entity)
{
    /*--- Get Original Entity ---*/
    var originalMaster = this.GetQuery("Products").Where(x => x.CategoryId == entity.CategoryId).FirstOrDefault();

    /*--- Master ---*/
    this.Context.ChangeEntityStateToEdited(originalMaster, entity);

    if (entity.Products != null)
    {
        /*--- Get Lists ---*/

        var addedList = entity
            .Products
            .Where(y => y.ProductId == 0)
            .ToList();

        var deletedList = originalMaster
            .Products
            .Where
            (
                x =>
                (
                    !entity.Products
                    .Select(y => y.ProductId)
                    .Contains(x.ProductId)
                )
            )
            .ToList();

        var editedList = entity.Products
         .Where
         (
             y => originalMaster
             .Products
             .Select(z => z.ProductId)
             .Contains(y.ProductId)
          )
          .ToList();

        /*--- Delete ---*/
        deletedList.ForEach(deletedProduct =>
        {
            originalMaster.Products.Remove(deletedProduct);
            this.Context.ChangeEntityStateToDeleted(deletedProduct);
        });

        /*--- Edit ---*/
        editedList.ForEach(editedProduct =>
        {
            var originalProduct = originalMaster.Products.Where(x => x.ProductId == editedProduct.ProductId).FirstOrDefault();
            this.Context.ChangeEntityStateToEdited(originalProduct, editedProduct);
        });

        /*---  Add ---*/
        addedList.ForEach(addedProduct =>
        {
            originalMaster.Products.Add(addedProduct);
        });
    }

    /*--- Save in context ---*/
    this.Context.Categories.Update(originalMaster);
    this.Context.SaveChanges();
}