Ответ 1
Вы должны использовать метод Attach().
Предположим, что я запрашиваю базу данных и загружаю список элементов. Затем я открываю один из элементов в форме подробного представления, и вместо повторного запроса элемента из базы данных я создаю экземпляр элемента из источника данных в списке.
Есть ли способ обновить запись базы данных, не извлекая запись отдельного элемента?
Вот пример, как я это делаю сейчас:
dataItem itemToUpdate = (from t in dataEntity.items
where t.id == id
select t).FirstOrDefault();
Затем, потянув за запись, я обновляю некоторые значения в элементе и нажимаю запись:
itemToUpdate.itemstatus = newStatus;
dataEntity.SaveChanges();
Я бы подумал, что будет лучший способ сделать это, любые идеи?
Вы должны использовать метод Attach().
Вы также можете использовать прямой SQL для базы данных, используя контекст хранилища данных. Пример:
dataEntity.ExecuteStoreCommand
("UPDATE items SET itemstatus = 'some status' WHERE id = 123 ");
По соображениям производительности вам может потребоваться передать переменные вместо одной жестко закодированной строки SQL. Это позволит SQL Server кэшировать запрос и повторно использовать его с параметрами. Пример:
dataEntity.ExecuteStoreCommand
("UPDATE items SET itemstatus = 'some status' WHERE id = {0}", new object[] { 123 });
UPDATE - для EF 6.0
dataEntity.Database.ExecuteSqlCommand
("UPDATE items SET itemstatus = 'some status' WHERE id = {0}", new object[] { 123 });
Если в элементе DataItem
есть поля EF, которые будут предварительно проверяться (например, поля с непустым значением), нам придется отключить эту проверку для этого контекста:
DataItem itemToUpdate = new DataItem { Id = id, Itemstatus = newStatus };
dataEntity.Entry(itemToUpdate).Property(x => x.Itemstatus).IsModified = true;
dataEntity.Configuration.ValidateOnSaveEnabled = false;
dataEntity.SaveChanges();
//dataEntity.Configuration.ValidateOnSaveEnabled = true;
В противном случае мы можем попробовать выполнить предварительную проверку и по-прежнему обновлять только один столбец:
DataItem itemToUpdate = new DataItem
{
Id = id,
Itemstatus = newStatus,
NonNullableColumn = "this value is disregarded - the db original will remain"
};
dataEntity.Entry(itemToUpdate).Property(x => x.Itemstatus).IsModified = true;
dataEntity.SaveChanges();
Предполагая, что dataEntity
есть System.Data.Entity.DbContext
Вы можете проверить запрос, сгенерированный добавлением этого параметра в DbContext
:
/*dataEntity.*/Database.Log = m => System.Diagnostics.Debug.Write(m);
Код:
ExampleEntity exampleEntity = dbcontext.ExampleEntities.Attach(new ExampleEntity { Id = 1 });
exampleEntity.ExampleProperty = "abc";
dbcontext.Entry<ExampleEntity>(exampleEntity).Property(ee => ee.ExampleProperty).IsModified = true;
dbcontext.Configuration.ValidateOnSaveEnabled = false;
dbcontext.SaveChanges();
Результат TSQL:
exec sp_executesql N'UPDATE [dbo].[ExampleEntities]
SET [ExampleProperty ] = @0
WHERE ([Id] = @1)
',N'@0 nvarchar(32),@1 bigint',@0='abc',@1=1
Примечание:
Строка IsModified = true необходима, потому что, когда вы создаете новый объект ExampleEntity (только при заполнении свойства Id), все остальные свойства имеют свои значения по умолчанию (0, null и т.д.). Если вы хотите обновить БД "значением по умолчанию", это изменение не будет обнаружено инфраструктурой сущностей, а затем БД не будет обновляться.
В примере:
exampleEntity.ExampleProperty = null;
не будет работать без строки "IsModified = true", потому что свойство ExampleProperty уже имеет значение null, когда вы создали пустой объект ExampleEntity, вам нужно сказать EF, что этот столбец должен быть обновлен, и это цель эта строка.
Эта статья как часть Microsoft Getting Started объясняет состояния сущностей и как это сделать:
Добавить/Прикрепить и сущности >
Посмотрите на раздел "Присоединение существующего, но измененного объекта к контексту"
Теперь я прошу прочесть оставшиеся уроки.
Вообще говоря, если вы использовали Entity Framework для запроса всех элементов и сохранили объект сущности, вы можете обновить отдельные элементы объекта сущности и вызвать SaveChanges()
по завершении. Например:
var items = dataEntity.Include("items").items;
// For each one you want to change:
items.First(item => item.id == theIdYouWant).itemstatus = newStatus;
// After all changes:
dataEntity.SaveChanges();
Поиск одного элемента, который вы хотите, не должен генерировать новый запрос.