Используйте linq для генерации прямого обновления без выбора - PullRequest
43 голосов
/ 15 января 2009

Всем привет.

Я все еще изучаю LINQ, так что прости меня, если это наивно. Когда вы имеете дело с SQL напрямую, вы можете генерировать команды обновления с условными выражениями без выполнения оператора select.

Когда я работаю с linq, я, кажется, следую примеру:

  1. Выбор сущностей
  2. Изменить сущности
  3. Отправить изменения

Что я хочу сделать, так это прямое обновление с использованием linq и отложенного выполнения. Возможно ли, что фактическое выполнение происходит непосредственно в SQL без каких-либо данных, передаваемых клиенту?

DataContext dc = new DataContext

var q = from product in dc.Products
        where product.Type = 1
        set product.Count = 0

dc.SubmitChanges

Таким образом, по сути, LINQ имеет всю необходимую информацию, БЕЗ использования select для генерации команды обновления. Было бы запустить SQL:

Update Products Set Count = 0 Where Type = 1

Существует ли ключевое слово типа "set" в LINQ?

Ответы [ 7 ]

45 голосов
/ 28 июля 2010

Вы можете позволить LINQ-to-SQL генерировать операторы обновления:

Foo foo=new Foo { FooId=fooId }; // create obj and set keys
context.Foos.Attach(foo);
foo.Name="test";
context.SubmitChanges();

В вашем Dbml установите UpdateCheck = "Никогда" для всех свойств.

Это сгенерирует один оператор обновления без необходимости выбирать сначала.

Одно предостережение: если вы хотите установить Name в null, вам придется инициализировать объект foo другим значением, чтобы Linq мог обнаружить изменение:

Foo foo=new Foo { FooId=fooId, Name="###" };
...
foo.Name=null;

Если вы хотите проверить метку времени при обновлении, вы также можете сделать это:

Foo foo=new Foo { FooId=fooId, Modified=... }; 
// Modified needs to be set to UpdateCheck="Always" in the dbml
29 голосов
/ 15 января 2009

Нет, ни LINQ, ни LINQ to SQL не имеют возможностей обновления на основе набора.

В LINQ to SQL вы должны запросить объект, который хотите обновить, обновить поля / свойства по мере необходимости, затем вызвать SubmitChanges (). Например:

var qry = from product in dc.Products where Product.Name=='Foobar' select product;
var item = qry.Single();
item.Count = 0;
dc.SubmitChanges();

Если вы хотите сделать дозирование:

var qry = from product in dc.Products where Product.Type==1 select product;
foreach(var item in qry)
{
  item.Count = 0;
}
dc.SubmitChanges();

В качестве альтернативы, вы можете написать запрос самостоятельно:

dc.ExecuteCommand("update Product set Count=0 where Type=1", null);
3 голосов
/ 12 ноября 2009

Платформа PLINQO (http://plinqo.com)) использует пакетное обновление LINQ для выполнения обновлений

context.Task.Update(t => t.Id == 1, t2 => new Task {StatusId = 2});

Это будет выполнять Update Task Set StatusId = 2 Where Id = 1

3 голосов
/ 15 января 2009

Linq 2 SQL не имеет прямой вставки / обновления / удаления эквивалентов SQL. В V1 единственными обновлениями, которые вы можете сделать с помощью linq, считается SubmmitChanges в контексте или если вы переходите к sql.

Однако некоторые люди пытались преодолеть это ограничение linq с помощью пользовательских реализаций.

Пакетное обновление Linq.

0 голосов
/ 14 июня 2018

Вы можете использовать Расширения Entity Framework библиотека, она поддерживает пакетное обновление и пакетное объединение, однако библиотека не является бесплатной:

PM> Install-Package Z.EntityFramework.Extensions

using Z.EntityFramework.Plus;

...

dc.Products
    .Where(q => q.Type == 1)
    .Update(q => new Product { Count = 0 });
0 голосов
/ 23 ноября 2016

Используйте этот метод расширения: EntityExtensionMethods.cs

public static void UpdateOnSubmit<TEntity>(this Table<TEntity> table, TEntity entity, TEntity original = null)
    where TEntity : class, new()
{
    if (original == null)
    {
        // Create original object with only primary keys set
        original = new TEntity();
        var entityType = typeof(TEntity);
        var dataMembers = table.Context.Mapping.GetMetaType(entityType).DataMembers;
        foreach (var member in dataMembers.Where(m => m.IsPrimaryKey))
        {
            var propValue = entityType.GetProperty(member.Name).GetValue(entity, null);
            entityType.InvokeMember(member.Name, BindingFlags.SetProperty, Type.DefaultBinder,
                original, new[] { propValue });
        }
    }

    // This will update all columns that are not set in 'original' object. For
    // this to work, entity has to have UpdateCheck=Never for all properties except
    // for primary keys. This will update the record without querying it first.
    table.Attach(entity, original);
}

Чтобы использовать его, убедитесь, что объект entity, который вы передаете методу UpdateOnSubmit, имеет все свойства первичного ключа, установленные для записи, которую вы хотите обновить. Затем этот метод обновит запись с оставшимися свойствами объекта entity, не тянув сначала запись.

После вызова UpdateOnSubmit, обязательно позвоните SubmitChanges(), чтобы изменения вступили в силу.

0 голосов
/ 29 апреля 2014

Попробуйте это:

dbEntities.tblSearchItems
     .Where(t => t.SearchItemId == SearchItemId)
     .ToList()
     .ForEach(t => t.isNew = false);
dbEntities.SaveChanges();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...