Вашего обновление ...
var f = db.Foos.First(x => someEqualityTest(foo));
f = foo;
... не будет работать, потому что вы не изменяете заряженную и прикрепленную объект f
на всех, вы просто перезаписать переменную f
с обособленным объектом foo
. Прикрепленный объект все еще находится в контексте, но после загрузки он не был изменен, и у вас больше нет переменной, которая указывает на нее. SaveChanges
ничего не сделает в этом случае.
В «стандартные опции» Вы находитесь:
var f = db.Foos.First(x => someEqualityTest(foo));
db.Entry(f).State = EntityState.Modified;
или просто
db.Entry(foo).State = EntityState.Modified;
// attaches as Modified, no need to load f
Это помечает все свойства, измененные - независимо от того, действительно ли они изменены или нет - и будет посылать UPDATE для каждого столбца в базе данных.
Второй вариант, который только будет отмечать действительно измененные свойства, как модифицированное и только послать UPDATE для измененных столбцов:
var f = db.Foos.First(x => someEqualityTest(foo));
db.Entry(f).CurrentValues.SetValues(foo);
Теперь, с 2 миллионов объектов для обновления вы не имеете «стандарт », и возможно, что оба варианта, особенно второй, который, вероятно, использует отражение внутри, чтобы сопоставить имена свойств источника и целевого объекта, слишком медленны.
Лучшим вариантом при обновлении является Change Tracking Proxies. Это означало бы, что вам нужно пометить КАЖДОЕ свойство в классе сущности как virtual
(а не только свойства навигации, но также и скалярные свойства) и что вы не отключите создание прокси-серверов отслеживания изменений (по умолчанию оно включено).
Когда вы загружаете свой объект f
из базы данных, EF создаст тогда динамический прокси-объект (полученный из вашей сущности), похожий на ленивые прокси-серверы загрузки, который имеет код, введенный в каждый набор свойств, чтобы поддерживать флаг, если свойство имеет были изменены или нет.
Отслеживание изменений, предоставляемое прокси, намного быстрее, чем отслеживание изменений на основе моментального снимка (что происходит в SaveChanges
или DetectChanges
).
Я не уверен, хотя если два упомянутых выше варианта быстрее, если вы используете прокси-серверы отслеживания изменений. Вполне возможно, что вам нужно вручную задание свойств, чтобы получить лучшую производительность:
var f = db.Foos.First(x => someEqualityTest(foo));
f.Property1 = foo.Property1;
f.Property2 = foo.Property2;
// ...
f.PropertyN = foo.PropertyN;
В моем опыте в аналогичной ситуации обновления с несколькими тысяч объектов нет реальной альтернативы для изменения отслеживания проксите в отношении производительности.
Можете ли вы пролить немного больше света на то, как проверить, если два экземпляра Foo равны? Является ли это простым сопоставлением идентификаторов? –
Может быть, я просто пытался обобщить специфику и сосредоточиться на более крупных логических аспектах решения – Didaxis