Search code examples
c#asp.netasp.net-mvcentity-frameworkaspnetboilerplate

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


Im using asp.net boilerplate with entity framework. I have 2 entities: Product and Supplier with many to many relationship.

My problem: When i save a product with one or more suppliers, The product and the relation on supplierProduct table is saved but the supplier record is duplicated on supplier table.

I read that happens because there are 2 entities from different contexts, so i need "attach" the suppliers to Products context. I dont know how to do it. Someone can help me?

My entities:

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

My domain service called 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);
        }
    }

My Application Service called ProductAppService:

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

My CreateProductInput Data transfer object

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

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

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

Solution

  • Following the Ivan Stoev comment i figure out how solve it. I implemented a custom repository and attached my entities to the dbcontext there.

    This link shows in details how create a custom repository.

    In resume:

    1- Create a custom repository INTERFACE

    2- Implement the custom repository+

    3- Create a method there and use the dbcontext.attach(entity) to attach to the context the entity thats was duplicating and save the context.

    4- Replace the IRepository used on domain service for the custom repository.

    5- Use the custom created method and be happy.

    Msg here if its not clear enough.