web-dev-qa-db-ja.com

linqを使用して、選択なしで直接更新を生成する

皆さん、こんにちは。

私はまだ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

「セット」のようなキーワードはLINQに存在しますか?

43
Spence

いいえ、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);
30
Randolpho

実際に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
45
laktak

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

Linq 2 SQLには、SQLに相当する挿入/更新/削除を直接行う機能はありません。 V1では、linqを使用して実行できる唯一の更新は、コンテキスト上またはSQLにフォールバックした場合のSubmmitChangesと見なされます。

ただし、一部の人々はカスタム実装を使用してlinqのこの制限を克服しようとしました。

Linqバッチ更新。

3
Pop Catalin

この拡張メソッドを使用します: 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

Entity Framework Extensions ライブラリを使用できます。これはバッチ更新とバッチマージをサポートしますが、ライブラリは無料ではありません。

PM>インストールパッケージZ.EntityFramework.Extensions

using Z.EntityFramework.Plus;

...

dc.Products
    .Where(q => q.Type == 1)
    .Update(q => new Product { Count = 0 });
0
koryakinp