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

本文关键字:实体 框架 关系 更新 连接 断开 环境 插入 | 更新日期: 2023-09-27 18:08:23

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

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

现在我也有一个集合对内容,称为文件。这用于将文件引用到内容实体。

实体框架因此创建了名为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的文件。我正在传递这个,因为我希望实体框架在两个实体之间创建一个关系。

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

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

所有这些似乎做的,是更新我的内容实体和更新文件实体。没有插入关系?有人能帮我插入关系吗?如果它在更新时已经存在,会发生什么?实体框架能帮我解决这个问题吗?

当一切都断开时,似乎很难处理实体??还是只有我这样?在我的单元测试中,这是有效的,但是实体没有断开连接。

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

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

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

例如,下面的代码显示了如何在断开连接的场景中保存带有子产品的类别:
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();
}