Обновить запись без предварительного запроса? - PullRequest
87 голосов
/ 18 ноября 2010

Допустим, я запрашиваю базу данных и загружаю список элементов. Затем я открываю один из элементов в форме подробного вида и вместо повторного запроса элемента из базы данных создаю экземпляр элемента из источника данных в списке.

Можно ли как-то обновить запись в базе данных, не выбирая запись отдельного элемента?

Вот пример того, как я делаю это сейчас:

dataItem itemToUpdate = (from t in dataEntity.items
                                 where t.id == id
                                 select t).FirstOrDefault();

Затем, после извлечения записи, я обновляю некоторые значения в элементе и возвращаю запись обратно:

itemToUpdate.itemstatus = newStatus;
dataEntity.SaveChanges();

Я думаю, что есть лучший способ сделать это, есть идеи?

Ответы [ 7 ]

67 голосов
/ 18 ноября 2010
32 голосов
/ 20 декабря 2011

Вы также можете использовать прямой 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 });

ОБНОВЛЕНИЕ - для EF 6.0

dataEntity.Database.ExecuteSqlCommand
       ("UPDATE items SET itemstatus = 'some status' WHERE id = {0}", new object[] { 123 });
8 голосов
/ 16 июня 2017

Код:

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, ноль и т. д.).Если вы хотите обновить БД с помощью «значения по умолчанию», изменение не будет обнаружено структурой сущностей, а затем БД не будет обновлено.

Например:

exampleEntity.ExampleProperty = null;

не будет работать без строки «IsModified = true», потому что свойство ExampleProperty уже имеет значение null, когда вы создали пустой объект ExampleEntity, вам нужно сказать EF, что этот столбец должен быть обновлен, и это является целью этой строки.

7 голосов
/ 09 июня 2017

Если DataItem имеет поля, которые EF будет предварительно проверять (например, поля, не допускающие значения NULL), нам придется отключить эту проверку для этого контекста:

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);
2 голосов
/ 11 мая 2013

Эта статья как часть Начало работы Microsoft объясняет состояния сущностей и как это сделать:

Добавить / Присоединить и Сущности

Посмотрите на раздел «Присоединение существующего, но измененного объекта к контексту»

Теперь я прочитаю остальные уроки.

0 голосов
/ 28 августа 2018

В EF Core работает несколько иначе:

Может быть более быстрый способ сделать это в EF Core, но следующее обеспечивает ОБНОВЛЕНИЕ без необходимости выполнять SELECT (протестировано с EF Core 2 и JET в .NET Framework 4.6.2): ​​

Убедитесь, что ваша модель не имеет свойств IsRequired

Затем используйте следующий шаблон (в VB.NET):

    Using dbContext = new MyContext()
        Dim bewegung = dbContext.MyTable.Attach(New MyTable())
        bewegung.Entity.myKey = someKey
        bewegung.Entity.myOtherField = "1"

        dbContext.Entry(bewegung.Entity).State = EntityState.Modified
        dbContext.Update(bewegung.Entity)

        Dim BewegungenDescription = (From tp In dbContext.Model.GetEntityTypes() Where tp.ClrType.Name = "MyTable" Select tp).First()
        For Each p In (From prop In BewegungenDescription.GetProperties() Select prop)
            Dim pp = dbContext.Entry(bewegung.Entity).Property(p.Name)
            pp.IsModified = False
        Next
        dbContext.Entry(bewegung.Entity).Property(Function(row) row.myOtherField).IsModified = True
        dbContext.SaveChanges()
    End Using
0 голосов
/ 18 ноября 2010

Вообще говоря, если вы использовали 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();

Поиск одного элемента, который вы хотите, не должен генерировать новый запрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...