Обновить конкретный столбец с использованием LINQ to SQL без загрузки всей сущности [duplicate]

Я всегда это делаю,

f = open('filename.txt', 'a')
f.write("stuff")
f.close()

Это просто, но очень полезно.

43
задан Spence 25 May 2009 в 06:46
поделиться

7 ответов

Нет, ни 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);
29
ответ дан Randolpho 20 August 2018 в 18:05
поделиться
  • 1
    Это код, который у меня есть, мне было интересно, имеет ли LINQ синтаксис для него. Приветствия для ответа, хотя, имеет смысл иметь обновления, происходящие на C #, потому что я предполагаю, что если вы хотите написать SQL, вы должны просто написать sql, как это делает команда выполнения. – Spence 15 January 2009 в 00:42
  • 2
    Согласен; Я предпочитаю подход внутри кода. – Randolpho 21 January 2009 в 18:00
  • 3
    Это действительно глупо, linq to sql должно иметь поле обновления – jdelator 9 July 2009 в 07:20
  • 4
    Этот ответ неверен. См. Ответ Криса ниже. – Peter Ruderman 29 November 2010 в 16:32
  • 5
    @PeterRuderman Прилагаемый ответ ниже требует знания fooId. Очень немногие сценарии (и, в частности, мои) не хотят знать эту информацию, просто переведите обновление против SQL. Ниже полезно, если у вас есть другие знания первичных ключей для обновления. Также это будет обновлять только одну строку, а не полную таблицу, и не будет увеличивать производительность на основе набора. – Spence 30 November 2016 в 02:54

Попробуйте следующее:

dbEntities.tblSearchItems
     .Where(t => t.SearchItemId == SearchItemId)
     .ToList()
     .ForEach(t => t.isNew = false);
dbEntities.SaveChanges();
3
ответ дан Highmastdon 20 August 2018 в 18:05
поделиться
  • 1
    Амит, вызов "ToList" будет загружать все элементы из базы данных в память. Foreach работает в памяти, а затем savechanges проталкивают их обратно. Я был за чем-то, что создало бы оператор SQL & quot; Обновить элементы, где условие & quot ;, которое не загружает ЛЮБЫЕ данные локально. – Spence 16 May 2014 в 06:40

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

PM> Install-Package Z. EntityFramework.Extensions

using Z.EntityFramework.Plus;

...

dc.Products
    .Where(q => q.Type == 1)
    .Update(q => new Product { Count = 0 });
0
ответ дан koryakinp 20 August 2018 в 18:05
поделиться

Вы можете позволить 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 = «Никогда» для всех свойств.

Это приведет к созданию одиночный оператор обновления, не требуя первого выбора.

Одно предупреждение: если вы хотите установить значение 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
44
ответ дан laktak 20 August 2018 в 18:05
поделиться
  • 1
    Однако его не совсем установлено. Его классный, чтобы знать синтаксис прикрепления, хотя – Spence 1 December 2010 в 00:15
  • 2
    Другой способ сделать это: context.Foos.Attach(foo, original: new Foo { FooId = fooId });. Это обновит все свойства, которые не заданы в исходном объекте. – orad 22 November 2016 в 03:04

Используйте этот метод расширения: 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
ответ дан orad 20 August 2018 в 18:05
поделиться
  • 1
    Спасибо Ораду. Это соответствует ответу laktak, но по-прежнему имеет ту же проблему, что и на самом деле выводит одну строку и знание таблицы. Мой вопрос заключался в том, может ли LINQ генерировать запрос на основе набора на SQL, который изначально не будет. – Spence 30 November 2016 в 02:55
  • 2
    Привет @Spence, я не думаю, что обновление пакета set возможно через LINQ, вы можете использовать метод AttachAll, но я думаю, что он все равно выполнит отдельные команды UPDATE для каждой строки. Мое решение делает прямое обновление без выбора, как в заголовке вопроса, но если ваш конкретный вопрос заключается в том, как выполнять пакетное обновление, принятый ответ правильный. – orad 30 November 2016 в 20:09

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

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

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

3
ответ дан Stephen Kennedy 20 August 2018 в 18:05
поделиться
  • 1
    Привет, друг, это было действительно интересно читать. Будем надеяться, что некоторые из них попадают в C # 4 или 5, потому что возможность обновления и удаления в партиях - это единственное, что фактически отсутствует в LINQ. – Spence 15 January 2009 в 00:40

Структура 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
ответ дан Highmastdon 20 August 2018 в 18:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: