Сравнивает ли ядро ​​EF значение для включения столбцов в оператор обновления? - PullRequest
0 голосов
/ 09 октября 2019

У меня есть следующий код

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 столбцов.

Ответы [ 2 ]

0 голосов
/ 10 октября 2019

Ваша первая сущность получается из контекста, поэтому по умолчанию контекст начинает отслеживать ее немедленно, а это означает, что любая извлекаемая вами сущность будет сохранена в DbContext вместе с копией его исходных значений. Когда вы изменяете значения свойств отслеживаемой сущности, контекст меняет EntityState для сущности на Modified, и ChangeTracker записывает старые значения свойств и новые значения свойств. Когда вызывается SaveChanges, база данных генерирует и выполняет инструкцию UPDATE, так как ChangeTracker отслеживает, какие свойства были изменены, контекст выдаст инструкцию SQL, которая обновляет только те свойства, которые были изменены, он сравнивает их с ихисходные значения для определения обновленных свойств.

Если вас интересуют конкретные столбцы, вы можете отключить запрос Отслеживание во время:

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

Затем сообщите контексту, какое свойство вы хотите изменить, контекствыдаст обновление оператора SQL без сравнения:

item.Name = "213213";
_context.Attach(item).Property(x => x.Name).IsModified = true;
_context.SaveChanges();
0 голосов
/ 09 октября 2019

Контекст имеет внутренний трекер изменений, который, как следует из названия, отслеживает изменения, внесенные в сущности. Это не сравнение того, что находится в базе данных, это просто замечание свойств, значения которых были изменены в коде. В случаях, когда вы изменяете только одно или несколько свойств, EF выдаст инструкцию обновления, которая включает в себя только столбцы для свойств, которые были изменены, но это не делается интеллектуальным способом. Другими словами, если вы измените свойство с тем же значением, которое оно имело ранее (либо явно, либо с помощью некоторых автоматических средств, таких как библиотека, например, AutoMapper), оно также включит этот столбец в оператор обновления, несмотря на то, что фактическое значение не изменилось.

...