问题
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