实体框架:更新记录,包括在Net Core 3中

Earlwaltonluv3462

如何使用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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

更新ASP.NET Core实体框架中的实体类

使用 .Net Core 5 中的存储库模式从带有实体框架的 Sql Server 中选择不同的记录

如何从ASP.NET Core中的实体框架中的数据库更新VS 2019中的模型

无法更新实体框架中的记录

记录实体框架.Net Core 2.2 EF以调试输出窗口

C#-使用实体框架核心3 HasConversion将字段转换为.Net Core 3.1中的JSON

实体框架.NET Core问题

.NET Core中的Unity框架

在ASP.NET Core中插入/更新记录时出错

如何在实体框架中更新表的所有记录?

MVC实体框架:表中多个记录的更新字段

使用ASP.NET Core中的联接查询在实体框架中获取用户角色

带有Firebird数据库和字符集的.Net Core 3实体框架无

使用 MSSQL 和 .Net Core 避免实体框架中的重复条目

在asp net core实体框架mvc中从数据库绑定菜单和子菜单

带有实体框架的ASP.NET Core MVC中的索引方法不接受参数

如何在.NET Core 3.0实体框架中执行组联接?

.Net Core中的通用存储库模式与实体框架有什么关系

ASP.Net Core - 实体框架 - 调用没有返回数据的存储过程(在 void 方法中)

EntityTypeBuilder <T>中的OnDelete ASP.NET Core 2实体框架

Net Core:将两个类成员映射到实体框架中的一列

实体框架:为Net Core中的先前版本运行EF迁移

InvalidOperationException:序列不包含任何元素。在带有实体框架的Asp.net Core MVC中

如何软删除asp.net core 2中具有集合的实体中的记录?

.NET Core 3中的ExecuteSqlRaw参数查询

更新 EF Core 中的相关实体

在EF Core中添加或更新实体

实体框架中的不同记录

实体框架单向关系.Net Core 3.1