使用 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- 使用自定义创建的方法并开心。
如有不明白的地方请留言
我将 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- 使用自定义创建的方法并开心。
如有不明白的地方请留言