Does EF core compares value to include columns in update statement?

烈酒焚心 提交于 2020-06-28 05:25:17

问题


I have the following code

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();

in the above query i am assigning the same Confidence but changing the ModifiedDateTime EF generates the following 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

Note that EF is not including Confidence column in the update statement. I am assuming, EF has to compare the original value with new value and if there is a change then only include those columns in the update statement.

Is that correct assumption?

I am asking this question because the WorkOrder table also has 4 nvarchar(max) columns. The data in these columns is long string. If my assumption is correct then EF also has to compare these 4 columns to decide to whether those column needs to include in the update query or not. And that comparison will be slower and may cause performance. Then I may create separate satellite table just for these 4 columns.


回答1:


The context has an internal change tracker, which as the name indicates, tracks changes made to entities. It's not comparing what's in the database, it's simply noting properties that have had their values modified in code. In cases where you change only a single or handful of properties, EF will issue an update statement which only includes the columns for properties that were modified, but it's not doing so in an intelligent way. In other words, if you modify a property with the same value it had before (either explicitly or via some automatic means like a library like AutoMapper), it will include that column in the update statement as well, despite the actual value being unchanged.




回答2:


Your first entity is obtained by the context, so by default the context begins tracking it immediately, which means that any entity you retrieve will be stored in the DbContext along with a copy of its original values. When you alter property values on a tracked entity, the context changes the EntityState for the entity to Modified and the ChangeTracker records the old property values and the new property values. When SaveChanges is called, an UPDATE statement is generated and executed by the database , since the ChangeTracker tracks which properties have been modified, the context will issue a SQL statement that updates only those properties that were changed , it will compare them with their original values to determine the updated properties .

If you concern about the specific columns , you can disable the Tracking while query :

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

Then tell context which property you want to modify , context will issue an SQL statement updating without compare :

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


来源:https://stackoverflow.com/questions/58307895/does-ef-core-compares-value-to-include-columns-in-update-statement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!