皆さん、こんにちは。
私はまだ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に存在しますか?
いいえ、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-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"を設定します。
これにより、単一の更新ステートメントが生成されます最初に選択を行う必要はありません。
注意点の1つ: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
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 2 SQLには、SQLに相当する挿入/更新/削除を直接行う機能はありません。 V1では、linqを使用して実行できる唯一の更新は、コンテキスト上またはSQLにフォールバックした場合のSubmmitChangesと見なされます。
ただし、一部の人々はカスタム実装を使用してlinqのこの制限を克服しようとしました。
この拡張メソッドを使用します: 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()
を呼び出してください。
Entity Framework Extensions ライブラリを使用できます。これはバッチ更新とバッチマージをサポートしますが、ライブラリは無料ではありません。
PM>インストールパッケージZ.EntityFramework.Extensions
using Z.EntityFramework.Plus;
...
dc.Products
.Where(q => q.Type == 1)
.Update(q => new Product { Count = 0 });