使用 Asp.net 样板在 Entity Framework 多对多关系中复制记录

Duplicating record in Entity Framework many to many relationship using Asp.net Boilerplate

我将 asp.net 样板与 entity framework 一起使用。 我有 2 个实体:具有多对多关系的产品和供应商。

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

我读到发生这种情况是因为有 2 个实体来自不同的上下文,所以我需要 "attach" 产品上下文的供应商。我不知道该怎么做。有人可以帮助我吗?

我的实体:

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

我的 angular 组件 product-list-component

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

我认为问题在于创建方法中发生的事情以及传递给它的内容。

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) 值的产品。

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

根据 Ivan Stoev 的评论,我想出了解决办法。我实现了一个自定义存储库并将我的实体附加到那里的 dbcontext。

This link 详细说明如何创建自定义存储库。

简历中:

1- 创建自定义存储库界面

2- 实现自定义存储库+

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

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

5- 使用自定义创建的方法并开心。

如有不明白的地方请留言