Доброго времени суток всем.
Я все еще изучаю LINQ, так что простите меня, если это наивно. Когда вы имеете дело с SQL напрямую, вы можете генерировать команды обновления с условными выражениями без выполнения оператора select.
Когда я работаю с linq, мне кажется, что я следую следующему шаблону:
Я хочу сделать прямое обновление с использованием 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
Существует ли в LINQ такое ключевое слово, как "set"?
Приведенные ниже ответы не разрешают обновления на основе наборов, как я описал, но они интересны.





Linq 2 SQL не имеет прямых эквивалентов SQL для вставки / обновления / удаления. В V1 единственные обновления, которые вы можете делать с помощью linq, - это SubmmitChanges в контексте или при откате на sql.
Однако некоторые люди пытались преодолеть это ограничение linq, используя собственные реализации.
Ура, дружище, это было действительно интересное чтение. Будем надеяться, что кое-что из этого попадет в C# 4 или 5, потому что возможность обновления и удаления пакетами - это единственное, чего действительно не хватает в LINQ.
Нет, ни 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);
Это код, который у меня есть, мне было интересно, есть ли у LINQ синтаксис для него. Приветствую вас за ответ, но имеет смысл, чтобы обновления происходили на C#, потому что я думаю, если вы хотите писать SQL, вы должны просто написать sql, как это делает функция команды execute.
Это действительно глупо, в linq to sql должно быть поле обновления
@PeterRuderman Прилагаемый ниже ответ требует знания fooId. Очень немногие сценарии (и в частности мой) не хотят знать эту информацию, просто переведите обновление на SQL. Ниже будет полезно, если у вас есть другие знания о первичных ключах для обновления. Кроме того, это обновит только одну строку, а не всю таблицу, и не получит увеличения производительности на основе набора.
Платформа 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
Фактически вы можете позволить 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 = "Never" для всех свойств.
Это сгенерирует один оператор обновления без предварительного выбора.
Одно предостережение: если вы хотите установить для 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
Однако это не совсем так. Круто знать синтаксис присоединения, хотя
Другой способ сделать это: context.Foos.Attach(foo, original: new Foo { FooId = fooId });. Это обновит все свойства, которые не установлены в исходной сущности.
Попробуй это :
dbEntities.tblSearchItems
.Where(t => t.SearchItemId == SearchItemId)
.ToList()
.ForEach(t => t.isNew = false);
dbEntities.SaveChanges();
Амит, вызов «ToList» загрузит все элементы из базы данных в память. Foreach работает в памяти, а затем сохраненные изменения распространяют их обратно. Я искал что-то, что могло бы создать оператор SQL «Обновить элементы, где условие», который не загружает ЛЮБЫЕ данные локально.
Используйте этот метод расширения: 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(), чтобы изменения вступили в силу.
Спасибо, Орад. Это соответствует ответу laktak, но по-прежнему имеет ту же проблему, что действительно выводит одну строку и знание таблицы. Мой вопрос заключался в том, может ли LINQ в конечном итоге выдать запрос обновления на основе набора для SQL, чего из коробки он не будет.
Привет @Spence, я не думаю, что пакетное обновление set возможно через LINQ, вы можете использовать метод AttachAll, но я думаю, что он все равно будет выполнять отдельные команды UPDATE для каждой строки. Мое решение выполняет прямое обновление без выбора, как в заголовке вопроса, но если ваш конкретный вопрос заключается в том, как выполнить пакетное обновление, принятый ответ правильный.
Вы можете использовать библиотеку Расширения 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 });
принятый в настоящее время ответ неверен - можете ли вы выбрать правильный?