EF Core 6直接从对象,NN,N-1,1-1更新数据
我很难将简单的更新端点添加到我的ASP.NET API中,我想更新实体以及他的关系。
我已经尝试了很多方法来在一个步骤中更新数据和关系,但是我有不同的错误,例如跟踪错误,连接表中的重复键或没有错误,但没有更新关系。
因此,首先,我尝试使用EF Core的跟踪使用连接状态更新数据。通常,我想将DTO Pattenr与AutoMapper一起使用,但为了保持简单,我有一个示例,没有这一步骤。
这是我对产品的模型配置:
public class Product
{
[Key]
public int ProductId { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
[Required]
public double Price { get; set; }
public SubCategorie SubCategorie { get; set; } //Relation n-1 to Table Subcategorie
public ICollection<Extra> Extra { get; set; } //Relation n-n to Table Extra
public DateTime CreatedDate { get; set; } = DateTime.Now;
public string CreatedBy { get; set; }
public string UpdatedBy { get; set; }
public DateTime UpdatedDate { get; set; }
}
andher与产品模型有关的额外模型的配置
public class Extra
{
[Key]
public int ExtraId { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Tooltip { get; set; }
[Required]
public double Price { get; set; }
public ICollection<Product> Products { get; set; } //Relation n-n to Table Product
public ICollection<ProductConfig> ProductConfigs { get; set; } //Relation n-n to Table PrductConfig
public DateTime CreatedDate { get; set; } = DateTime.Now;
public string CreatedBy { get; set; }
public string UpdatedBy { get; set; }
public DateTime UpdatedDate { get; set; }
}
以及dbContex中的onmodeLcreatin方法,我在这里配置了
// Product
// n-n to Extra
modelBuilder.Entity<Product>()
.HasMany<Extra>(e => e.Extra)
.WithMany(e => e.Products);
//n-n to Type
modelBuilder.Entity<Product>()
.HasMany<ProductType>(e => e.ProductType)
.WithMany(e => e.Products);
// n-1 to Subcategorie
modelBuilder.Entity<Product>()
.HasOne<SubCategorie>(e => e.SubCategorie)
.WithMany(e => e.Product);
// 1-n to productconfig
modelBuilder.Entity<Product>()
.HasMany<ProductConfig>(e => e.ProductConfigs)
.WithOne(e => e.Product);
此关系是与连接状态的示例。问题在这里,关系中没有任何事情发生,例如添加额外的对象并带有“ porductNew”输入时。
public async Task<Product> UpdateProduct(int productId, Product productNew)
{
try
{
if (productId == productNew.ProductId)
{
//valid
Product product = await _db.Product.AsNoTracking()
.Include(x => x.Extra)
.Include(x => x.ProductType)
.FirstOrDefaultAsync(x => x.ProductId == productId);
product = productNew;
await _db.SaveChangesAsync();
return product;
}
else
{
//invalid
throw new Exception("Id for updating and Id in the Data not match");
}
}
catch (Exception ex)
{
throw new Exception(ex.ToString());
}
}
当我将实体状态手动设置为修改时,我会有一个跟踪错误:“无法跟踪ISTNACE,因为另一个具有相同键值的实例……”
因此,我也尝试使用断开的状态架构。为此,我使用更新方法。那里的关系将是正确的,但是当我再次提交相同的更改时,EF核心将加入表中的状态设置为添加了
此模式的存储库:
public async Task<Product> UpdateProduct(int productId, Product productNew)
{
try
{
if (productId == productNew.ProductId)
{
//valid
Product product = await _db.Product.AsNoTracking()
.Include(x => x.SideDishs)
.Include(x => x.Extra)
.Include(x => x.ProductType)
.FirstOrDefaultAsync(x => x.ProductId == productId);
product = productNew;
var updatedProduct = _db.Product.Update(product);
await _db.SaveChangesAsync();
return product;
}
else
{
//invalid
throw new Exception("Id for updating and Id in the Data not match");
}
}
catch (Exception ex)
{
throw new Exception(ex.ToString());
}
}
这是EF Core Debugging的Changetracker。在这种情况下,加入表应具有比添加的状态修改的,因为关系没有变化。加入表中重复键的错误发生了:
extra {extraid:1}修改后的
Extraid:1 pk
createby:'admin'修改了
createddate:'19 .06.2022 09:54:16'修改
名称:'zwei Teller'修改
价格:0修改
工具提示:'das essen wird auf zwei teller serviert'
修改更新:修改
:'01 .01.0001 00:00:00:00'修改
productsconfigs
:[{productid:1}
]
更新 PK
CreatedBy: 'Admin' Modified
CreatedDate: '19.06.2022 09:55:27' Modified
Name: 'extra scharf' Modified
Price: 0 Modified
Tooltip: 'Gewürzt mit spezieller Chili Paste' Modified
UpdatedBy: Modified
UpdatedDate: '01.01.0001 00:00:00'改进的
产品configs:
产品:[{progucatid:1}]
外{extraid:1,productsProductId:1}添加了添加
:1 pk fk fk fk
productsproductid:1 pk
fk fk fk flk product offroductID {extraid {extract {extract offer:2,添加了product productuctid:1}
Extraid:2 PK FK
ProductsProductID:1 PK FK
产品{propartiD:1}修改的
productid:1 pk
createby:'admin'修改
createDate:'19 .06.2022 10:27:17'修改
描述:'beschreibung testprodified'修改后的
名称:' TestProdukt 1'修改
价格:15修改后的
子类别:fk未知
更新:'string'修改后的
更新date:'19 .06.2022 08:26:45'修改
productConfigs:
subcategorie:subcategorie
:subcategorie:extra
productType:[]
因此,有人描述了EF-Core6的更新顺序具有与外部对象进行更新的所有类型的EF-Core6更新顺序?
I have some trouble to add a simple update Endpoint to my asp.Net API where I want to update an Entity and also his relations.
I already tried a lot of ways to update the data and the relations in one step, but I had different errors, like tracking error, duplicate key in joining table or no error but the relation was not updated.
So first I tried to update my data using the connected State with the tracking of EF Core. Normaly I want to use the DTO Pattenr with Automapper but to keep it simple I have an example without this step between.
Here is my model configuration of product:
public class Product
{
[Key]
public int ProductId { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
[Required]
public double Price { get; set; }
public SubCategorie SubCategorie { get; set; } //Relation n-1 to Table Subcategorie
public ICollection<Extra> Extra { get; set; } //Relation n-n to Table Extra
public DateTime CreatedDate { get; set; } = DateTime.Now;
public string CreatedBy { get; set; }
public string UpdatedBy { get; set; }
public DateTime UpdatedDate { get; set; }
}
Andher the config of the extra model which is in n-n relation to the product model
public class Extra
{
[Key]
public int ExtraId { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Tooltip { get; set; }
[Required]
public double Price { get; set; }
public ICollection<Product> Products { get; set; } //Relation n-n to Table Product
public ICollection<ProductConfig> ProductConfigs { get; set; } //Relation n-n to Table PrductConfig
public DateTime CreatedDate { get; set; } = DateTime.Now;
public string CreatedBy { get; set; }
public string UpdatedBy { get; set; }
public DateTime UpdatedDate { get; set; }
}
and here the onModelCreatin Method in DBContex, where I configure the relations
// Product
// n-n to Extra
modelBuilder.Entity<Product>()
.HasMany<Extra>(e => e.Extra)
.WithMany(e => e.Products);
//n-n to Type
modelBuilder.Entity<Product>()
.HasMany<ProductType>(e => e.ProductType)
.WithMany(e => e.Products);
// n-1 to Subcategorie
modelBuilder.Entity<Product>()
.HasOne<SubCategorie>(e => e.SubCategorie)
.WithMany(e => e.Product);
// 1-n to productconfig
modelBuilder.Entity<Product>()
.HasMany<ProductConfig>(e => e.ProductConfigs)
.WithOne(e => e.Product);
Here is the example with the connected state. The problem is here that nothing at the relations happened, for example when an extra object is added and comes with the "porductNew" input.
public async Task<Product> UpdateProduct(int productId, Product productNew)
{
try
{
if (productId == productNew.ProductId)
{
//valid
Product product = await _db.Product.AsNoTracking()
.Include(x => x.Extra)
.Include(x => x.ProductType)
.FirstOrDefaultAsync(x => x.ProductId == productId);
product = productNew;
await _db.SaveChangesAsync();
return product;
}
else
{
//invalid
throw new Exception("Id for updating and Id in the Data not match");
}
}
catch (Exception ex)
{
throw new Exception(ex.ToString());
}
}
When I set the entity State manually to modified I have a tracking error "the istnace could not been tracked because another instance with the same keyvalue..."
So I tried also with the disconnected state schema. For this I use the update Method. There the relations will be added correct, but when i commit the same changes again, EF Core set the state inside the joining table to added than modified
Here is the repository for this pattern:
public async Task<Product> UpdateProduct(int productId, Product productNew)
{
try
{
if (productId == productNew.ProductId)
{
//valid
Product product = await _db.Product.AsNoTracking()
.Include(x => x.SideDishs)
.Include(x => x.Extra)
.Include(x => x.ProductType)
.FirstOrDefaultAsync(x => x.ProductId == productId);
product = productNew;
var updatedProduct = _db.Product.Update(product);
await _db.SaveChangesAsync();
return product;
}
else
{
//invalid
throw new Exception("Id for updating and Id in the Data not match");
}
}
catch (Exception ex)
{
throw new Exception(ex.ToString());
}
}
Here is the changetracker from EF Core debugging. The Joining table should in this case have the state modified than added because there was no change at the relations. The error of duplicate key in joining table happens:
Extra {ExtraId: 1} Modified
ExtraId: 1 PK
CreatedBy: 'Admin' Modified
CreatedDate: '19.06.2022 09:54:16' Modified
Name: 'zwei Teller' Modified
Price: 0 Modified
Tooltip: 'Das Essen wird auf zwei Teller serviert' Modified
UpdatedBy: Modified
UpdatedDate: '01.01.0001 00:00:00' Modified
ProductConfigs:
Products: [{ProductId: 1}]
Extra {ExtraId: 2} Modified
ExtraId: 2 PK
CreatedBy: 'Admin' Modified
CreatedDate: '19.06.2022 09:55:27' Modified
Name: 'extra scharf' Modified
Price: 0 Modified
Tooltip: 'Gewürzt mit spezieller Chili Paste' Modified
UpdatedBy: Modified
UpdatedDate: '01.01.0001 00:00:00' Modified
ProductConfigs:
Products: [{ProductId: 1}]
ExtraProduct {ExtraId: 1, ProductsProductId: 1} Added
ExtraId: 1 PK FK
ProductsProductId: 1 PK FK
ExtraProduct {ExtraId: 2, ProductsProductId: 1} Added
ExtraId: 2 PK FK
ProductsProductId: 1 PK FK
Product {ProductId: 1} Modified
ProductId: 1 PK
CreatedBy: 'Admin' Modified
CreatedDate: '19.06.2022 10:27:17' Modified
Description: 'Beschreibung Testprodukt' Modified
Name: 'Testprodukt 1' Modified
Price: 15 Modified
SubCategorieId: FK Unknown
UpdatedBy: 'string' Modified
UpdatedDate: '19.06.2022 08:26:45' Modified
ProductConfigs:
SubCategorie:
Extra: [{ExtraId: 1}, {ExtraId: 2}]
ProductType: []
So does anybody have a simple idea or know a documentation, where the update sequence for ef-core6 with all types of relations with external objects for updating is described?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当您找到数据并且数据将被修改时,您不应使用
asnotracking()
方法,请阅读有关跟踪与无跟踪查询。When you are finding the data and the data will be modified, you should not use the
AsNoTracking()
method, please read more about Tracking vs. No-Tracking Queries.