【问题标题】:Duplicating record in Entity Framework many to many relationship using Asp.net Boilerplate使用 Asp.net Boilerplate 在实体框架中复制多对多关系的记录
【发布时间】:2017-07-28 17:08:52
【问题描述】:

我正在使用带有实体框架的 asp.net 样板。 我有 2 个实体:具有多对多关系的产品和供应商。

我的问题:当我保存一个或多个供应商的产品时,供应商产品表上的产品和关系被保存,但供应商记录在供应商表上重复。

我读到这是因为有 2 个来自不同上下文的实体,所以我需要将供应商“附加”到 Products 上下文。我不知道该怎么做。有人可以帮助我吗?

我的实体:

public class Product : FullAuditedEntity
{

    public Product()
    {
        Suppliers = new HashSet<Supplier>();
    }

    public string Name { get; set; }

    public virtual ICollection<Supplier> Suppliers { get; set; }
}


public class Supplier : FullAuditedEntity
{
    public Supplier()
    {
        Products = new HashSet<Product>();
    }

    public string Name { get; set; }

    public virtual ICollection<Product> Products { get; set; }
}

我的域服务名为 ProductManager

public async Task<Product> Create(Product entity)
    {
        var product = _repositoryProduct.FirstOrDefault(x => x.Id == entity.Id);

        if (product != null)
        {
            throw new UserFriendlyException("Product already exists.");
        }
        else
        {
            return await _repositoryProduct.InsertAsync(entity);
        }
    }

我的应用服务名为 ProductAppService:

public async Task Create(CreateProductInput input)
    {
        Product output = Mapper.Map<CreateProductInput, Product>(input);
        await _productManager.Create(output);
    }

我的 CreateProductInput 数据传输对象

public class CreateProductInput
{
    public string Name { get; set; }

    public ICollection<Supplier> Suppliers { get; set; }
}

我的角度组件产品列表组件

    // GET Products
    function getProducts() {
        productService.listAll()
            .then(function (result) {
                vm.users = result.data;
            });
    }
    getProducts();

    // GET Suppliers
    function getSuppliers() {
        supplierService.listAll()
            .then(function (result) {
                vm.suppliers = result.data;
            });
    }
    getSuppliers();

    //Save the data
    vm.save = function () {
        abp.ui.setBusy();
        productService.create(vm.product)
            .then(function () {
                abp.notify.info(App.localize('SavedSuccessfully'));
                $uibModalInstance.close();
            }).finally(function () {
                abp.ui.clearBusy();
                getProducts();
            });
    }

【问题讨论】:

  • 您没有包含最相关的方法实现 - InsertAsyncProduct 存储库。
  • 这是一个来自 asp.net 样板的方法github.com/aspnetboilerplate/aspnetboilerplate
  • 嗯,默认的通用存储库实现非常幼稚,显然不适用于具有相关数据的实体。您很可能需要实现自定义存储库。
  • 我想我需要在某处“附加”相关实体。
  • Ivan Stoev,我创建了一个自定义仓库和一个名为 InsertAndAttach 的方法,我在其中手动将实体附加到上下文并解决了问题

标签: c# asp.net asp.net-mvc entity-framework aspnetboilerplate


【解决方案1】:

我认为问题在于 create 方法中发生了什么以及您传递给它的内容。

public async Task<Product> Create(Product entity)
{
    var product = _repositoryProduct.FirstOrDefault(x => x.Id == entity.Id);

    if (product != null)
    {
        throw new UserFriendlyException("Product already exists.");
    }
    else
    {
        return await _repositoryProduct.InsertAsync(entity);
    }
}

在我看来,您传递给 Create 方法的参数总是 Id == 0,因此它总是会落入 else 块并插入新实体

那是因为 CreateProductInput 没有要映射的 Id 属性。因此,它将始终映射到具有 Id (int = 0) 的默认值的产品。

您还可以在调用 Create 之前传递您的供应商实体的 id 并获取它们,这样它们应该会自动附加到 DbContext 而不会重复

【讨论】:

  • 嘿用户,tkx 的答案。我想出了如何解决这个问题,很快就会在这里发帖
【解决方案2】:

按照 Ivan Stoev 的评论,我想出了如何解决它。我实现了一个自定义存储库并将我的实体附加到那里的 dbcontext。

This link 详细展示了如何创建自定义存储库。

在简历中:

1- 创建自定义存储库接口

2- 实现自定义存储库+

3- 在那里创建一个方法并使用dbcontext.attach(entity) 将正在复制的实体附加到上下文并保存上下文。

4- 将域服务上使用的 IRepository 替换为自定义存储库。

5- 使用自定义创建的方法并快乐。

如果不够清楚,请在这里留言。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-28
    • 2011-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多