【问题标题】:Does EF core compares value to include columns in update statement?EF 核心是否比较值以包含更新语句中的列?
【发布时间】:2019-10-10 11:08:59
【问题描述】:

我有以下代码

var dbContext = Setup.ConfigureDBContext();
var wo = await dbContext.WorkOrders.Where(x => x.WorkOrderID == 88).SingleOrDefaultAsync();
var t = wo.Confidence;
wo.ModifiedDateTime = DateTime.UtcNow;
wo.Confidence = t;
await dbContext.SaveChangesAsync();

在上述查询中,我分配了相同的 Confidence,但更改了 ModifiedDateTime EF 生成如下 SQL

exec sp_executesql N'SET NOCOUNT ON;
UPDATE [WorkOrders] SET [ModifiedDateTime] = @p0
WHERE [WorkOrderID] = @p1 AND [VersionStamp] = @p2;
SELECT [VersionStamp]
FROM [WorkOrders]
WHERE @@ROWCOUNT = 1 AND [WorkOrderID] = @p1;

',N'@p1 int,@p0 datetime,@p2 varbinary(8)',@p1=88,@p0='2019-10-09 15:33:06.343',@p2=0x0000000000582A52

请注意,EF 在更新语句中不包括Confidence 列。我假设,EF 必须将原始值与新值进行比较,如果有变化,则只在更新语句中包含这些列。

这是正确的假设吗?

我问这个问题是因为WorkOrder 表也有 4 个 nvarchar(max) 列。这些列中的数据是长字符串。如果我的假设是正确的,那么 EF 还必须比较这 4 列来决定这些列是否需要包含在更新查询中。而且这种比较会比较慢,并且可能会导致性能下降。然后我可以为这 4 列创建单独的卫星表。

【问题讨论】:

    标签: entity-framework .net-core asp.net-core-2.0 asp.net-core-2.1 ef-core-2.0


    【解决方案1】:

    上下文有一个内部更改跟踪器,顾名思义,它跟踪对实体所做的更改。它不是比较数据库中的内容,它只是注意在代码中修改了其值的属性。如果您仅更改单个或少数几个属性,EF 将发出更新语句,其中仅包含已修改属性的列,但它不会以智能方式这样做。换句话说,如果您使用与之前相同的值修改属性(显式地或通过诸如 AutoMapper 之类的库之类的自动方式),它将在更新语句中包含该列,尽管实际值未更改。

    【讨论】:

    • 但它上面的代码不包括更新语句中的Confidence 列,即使我在代码中设置它也是如此。我知道 EF 具有更改跟踪器及其在内存中的跟踪更改。我的问题更多是关于比较。我假设跟踪器必须比较实体的所有属性的值才能知道该列是否需要包含
    【解决方案2】:

    您的第一个实体是由上下文获取的,因此默认情况下上下文会立即开始跟踪它,这意味着您检索到的任何实体都将与其原始值的副本一起存储在 DbContext 中。当您更改被跟踪实体的属性值时,上下文会将实体的 EntityState 更改为 Modified,并且 ChangeTracker 会记录旧属性值和新属性值。当调用SaveChanges 时,数据库会生成并执行一条UPDATE 语句,因为ChangeTracker 会跟踪哪些属性已被修改,上下文将发出一条SQL 语句,仅更新那些已更改的属性,并将它们与它们的属性进行比较原始值来确定更新的属性。

    如果您关心特定列,可以禁用查询时跟踪:

    var item = _context.Employees.Where(x=>x.ID==1).AsNoTracking().FirstOrDefault();
    

    然后告诉context你要修改哪个属性,context会发出一个不比较的SQL语句更新:

    item.Name = "213213";
    _context.Attach(item).Property(x => x.Name).IsModified = true;
    _context.SaveChanges();
    

    【讨论】:

      猜你喜欢
      • 2022-08-16
      • 1970-01-01
      • 2021-11-23
      • 1970-01-01
      • 2020-08-23
      • 2019-02-06
      • 2013-06-19
      • 2016-09-25
      • 1970-01-01
      相关资源
      最近更新 更多