如何使用Entity Framework Core中的包含项更新表?以下内容似乎可以更新客户交易记录,但不能更新产品ID。
客户和产品都具有变化的属性,但客户ID和产品ID保持不变。
public void ModifyTransaction(IEnumerable<CustomerTransaction> customerTransactionList)
{
foreach (var modifyItem in customerTransactionList)
{
var existingItem = _dbContext.Set<CustomerTransaction>().Include(x => x.Product)
.FirstOrDefault(x => x.CustomerTransactionId == modifyItem.CustomerTransactionId );
if (existingItem == null)
{
_dbContext.Add(existingItem );
}
else
{
_dbContext.Entry(existingItem).State = EntityState.Modified;
}
}
_dbContext.SaveChanges();
}
使用Net Core 3.1
此代码容易出现错误,具体情况视情况而定。在客户端和服务器之间传递实体类时,重要的是要了解传递回服务器的对象仅仅是序列化副本,而不是跟踪的实体。由于序列化的工作方式,在DbContext中获取两个均引用ID为14的Product的两个Transaction记录时,将引用相同的实体实例,反序列化时,同一对事务将具有两个单独的对象引用,每个对象均包含一个Product ID:14。
以您的示例为例,至少您需要执行以下操作:
foreach (var modifyItem in customerTransactionList)
{
var existingItem = _dbContext.CustomerTransactions
.Include(x => x.Product)
.SingleOrDefault(x => x.CustomerTransactionId == modifyItem.CustomerTransactionId );
var trackedProduct = _dbContext.Products.Local(x => x.ProductId == modifyItem.Product.ProductId).SingleOrDefault();
if (trackedProduct != null)
modifyItem.Product = trackedProduct;
else
_dbContext.Products.Attach(modifyItem.Product);
if (existingItem == null)
_dbContext.Add(modifyItem);
else
{
_dbContext.Entry(existingItem).CurrentValues.SetValues(modifyItem);
if(existingItem.Product.ProductId != modifyItem.Product.ProductId)
existingItem.Product = modifyItem.Product; // tracked reference.
}
}
_dbContext.SaveChanges();
}
这相当于检查您正在执行的现有交易。但是,我们还必须检查DbContext可能正在跟踪的任何相关实体(产品)的缓存副本。如果我们不这样做,并且尝试添加一个具有ID与该ID匹配的产品的交易,那么上下文已经在跟踪该交易,那么我们将收到PK违规或重复的产品记录,并创建一个新的产品ID,具体取决于您的产品PK已配置。(即DatabaseGenerated.Identity
列)如果找到本地缓存实例,我们将使用本地缓存实例更新Product引用,否则,我们将通知DbContext开始跟踪该产品实例。假设此方法不能接受新的产品作为此次通话的一部分,并且收到的产品记录应合法存在。处理新产品并验证传入的产品将需要其他条件代码和数据库检查。从那里,我们确定交易是更新还是插入。在更新的情况下,我们可以使用CurrentValues.SetValues
跨值(如上所述)或自动映射器进行复制,或者手动跨相关值进行复制。假设某笔交易可能会更改产品,我们还将对照已修改的产品检查产品ID,如果有所不同,则会更新产品参考。modifyItem.Product
此时将指向DbContext跟踪引用。
使用这样的方法更新实体可能会非常麻烦,因为您不仅要考虑检测新记录还是现有记录,而且还要考虑更新对DbContext已经跟踪的实体的引用。我的强烈建议是为显式的添加和更新操作采用视图模型,并尽可能原子地处理操作。即,与其传递可能包含要进行更新的更新或插入的事务集合,不如对每种奇异类型的更改进行更细化的调用。(更简单,更快的操作和更少的错误发生位置)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句