3

私は現在、linq2sql をデータベース アクセス フレームワークとして使用するプロジェクトに取り組まなければなりません。現在、基本的に次のことを行う多くの linq クエリがあります。

var result =    from <some_table>
                join <some_other_table>
                join <another_table>
                select <some_other_domain_model> // This is a non linq2SQL poco

return result.Where(<Some_Predicate>);

たとえば、3 つのテーブルを読み取り、コンテンツを 1 つの大きな上位モデルに照合して、ビューに送信するとします。ここで、ドメインの混合を無視します。それはあまり気にしないので、最終的な where 句です。

今、私はLinq2Sqlをあまり使用したことがないので、何が起こるかは次のように言うのが正しいでしょうか:

  1. from、join、join、select linq に基づいて SQL を生成する
  2. すべての行を取得する
  3. このすべてのデータを 1 つの大きなモデル (メモリ内) にマップする
  4. すべてのモデルをループし、該当するモデルのみを返します

これが私の質問の核心であるため、上記のフローが発生するかどうかは私の心の中では理にかなっていますが、4番目のステップよりもフレームワークをよく知っている人々によって議論されており、何らかの形でSQLに組み込まれています世代なので、すべてのレコードを引き戻すわけではありませんが、これを設定するためにすべてのデータを前もって必要とするため、どのようにそれを行うことができるかわかりません。行はすべて読み取られ、すでにメモリー内にあります。

データベース レベルで不要なレコードを除外するために、where 句を linq に移動するようにプッシュしようとしていますが、上記の仮定が正しいかどうかについて誰かがアドバイスできるかどうか疑問に思っていました。

== 編集 ==

これは linq2sql によって生成されたオブジェクトではなく、他の場所で転がされたランダムな poco ハンドであるという事実に注意を向けるためにコメントを追加しました。質問は LESS about"does it matter where I put the where clause"であり、詳細について"Does the where clause still get factored into the underlying query when it is applied to a non linq2sql object generated from a linq2sql query"です。

これは、私の理解の欠如がどこにあるのかをより強調することを願って、私が意味することの別のより簡潔な例です:

/*
    I am only going to put auto properties into the linq2sql entities,
    although in the real world they would be a mix of private backing
    fields with public properties doing the notiftying.
*/

[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.some_table_1")]
public class SomeLinq2SqlTable1
{
    [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="some_table_1_id", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
    public int Id {get;set;}
}

[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.some_table_2")]
public class SomeLinq2SqlTable2
{
    [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="some_table_2_id", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL", IsPrimaryKey=true, IsDbGenerated=true)]
    public int Id {get;set;}

    [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="some_table_2_name", AutoSync=AutoSync.OnInsert, DbType="Varchar NOT NULL", IsPrimaryKey=false)]
    public string Name {get;set;}
}

[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.some_table_3")]
public class SomeLinq2SqlTable3
{
    [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="some_table_3_id", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL", IsPrimaryKey=true, IsDbGenerated=true)]
    public int Id {get;set;}

    [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="some_table_3_other", AutoSync=AutoSync.OnInsert, DbType="Varchar NOT NULL", IsPrimaryKey=false)]
    public string Other {get;set;}
}

/*
    This is some hand rolled Poco, has NOTHING to do with Linq2Sql, think of it as 
    a view model of sorts.
*/
public class SomeViewModel
{
    public int Id {get;set;}
    public string Name {get;set;}
    public string Other {get;set;}
}

/*
    Here is psudo query to join all tables, then populate the
    viewmodel item from the query and finally do a where clause
    on the viewmodel objects.
*/
var result =    from // Linq2SqlTable1 as t1
                join // Linq2SqlTable2.id on Linq2SqlTable1.id as t2
                join // Linq2SqlTable3.id on Linq2SqlTable1.id as t3
                select new ViewModel { Id = t1.Id, Name = t2.Name, Other = t3.Other }

return result.Where(viewModel => viewModel.Name.Contains("some-guff"));

上記の例では、最終的な Where ステートメントは基になるクエリに組み込まれるのでしょうか、それとも viewModel の where によって検索が行われ、メモリ内で評価されるのでしょうか?

この質問が冗長で申し訳ありませんが、それに関するドキュメントはほとんどなく、これは非常に具体的な質問です。

4

3 に答える 3

5

Where節をこれ以上押し上げる必要はありません。resultある限り、どこでも問題ありませんIQueryable<T>(一部の場合T)。LINQ は構成可能です。実際、LINQ 構文を使用することと拡張メソッド構文を使用することの間にまったく違いはなく、どちらも同じように機能します。基本的に、クエリを作成するときは、要求されたもののモデルを構築しているだけです。反復を開始するまで何も実行されません ( 、など)。したがって、最後にエクストラを追加しても問題ありません。これは、作成されたクエリに組み込まれます。foreachToList()Where

これは、SQL 接続を監視することで非常に簡単に確認できます。whereTSQL に句が含まれており、SQL サーバーでフィルターが含まれていることがわかります。

これにより、柔軟な検索など、いくつかの興味深いシナリオが可能になります。

IQueryable<Customer> query = db.Customers;
if(name != null) query = query.Where(x => x.Name == name);
if(region != null) query = query.Where(x => x.Region == region);
...
if(dob != null) query = query.Where(x => x.DoB == dob);
var results = query.Take(50).ToList();

あなたの仮定に関しては、それらは正しくありません-それは実際には次のとおりです。

  1. 構成可能なクエリを構築する、(個別に) 構成する、結合する、結合する、選択する
  2. where を追加してクエリをさらに構成します (上記の構成と違いはありません)。
  3. 後で、クエリを繰り返します
    1. 完全に構成されたクエリから SQL を生成する
    2. 行を取得する
    3. モデルにマップ
    4. 結果を出す

SQL の生成は、クエリが繰り返されるときにのみ発生することに注意してください。それまでは、一日中作曲を続けることができます。反復されるまで、SQL サーバーには触れません。

于 2012-11-29T10:13:39.813 に答える
0

プロバイダーは、カスタム モデルから取り込まれたプロパティがデータベース テーブルの実際の列にどのようにマップされるか (クエリの select 句により) を認識しています。そのため、カスタム モデルのプロパティをフィルター処理するときに、テーブルのどの列をフィルター処理する必要があるかがわかります。選択したモデル (テーブルのすべての列を含むデザイナー定義のエンティティ、どこかで定義されたカスタム モデル、または必要なデータのみを含む匿名型) を FROM 句の前の選択した列と考えてください。 SQL クエリ。匿名モデルを選択すると、モデルのフィールドが SQL の SELECT リストに対応していることを簡単に認識できます。

最も重要なこと: それはただのクエリであることを常に覚えておいてくださいvar result = from ...... iterated になるまでresult.ToArray()queryの代わりに変数を呼び出すようにしてくださいresult。もう一度見たときに、世界が新しい新しい色になる可能性があります。

于 2013-05-30T13:47:06.090 に答える
0

私は LINQtoSQL のベスト プラクティスについて少し調べました。これは、自分のプロジェクトで常にこのテクノロジを使用しているためです。私のブログ投稿を見てください。多分それはあなたを助けることができます。

http://msguy.net/post/2012/03/20/LINQ-to-SQL-Practices-and-approaches.aspx

于 2012-11-29T13:45:45.550 に答える