6

ここで DataConvert.ToThema() を使用してテーブル オブジェクトをカスタム ビジネス オブジェクトに変換するように、コンパイル済みのクエリに関数を含めると、裏で何が起こりますか。

public static class Queries
{
    public static Func<MyDataContext, string, Thema> GetThemaByTitle
    {
        get
        {
            var func = CompiledQuery.Compile(
                (MyDataContext db, string title) =>
                    (from th in elan.tbl_Thema
                     where th.Titel == title
                     select DataConvert.ToThema(th)).Single()
                     );
            return func;
        }
    }
}

public static class DataConvert
{
    public static Thema ToThema(tbl_Thema tblThema)
    {
        Thema thema = new Thema();

        thema.ID = tblThema.ThemaID;
        thema.Titel = tblThema.Titel;
        // and some other stuff

        return thema;
    }
}

そしてそれをこのように呼びます

Thema th = Queries.GetThemaByTitle.Invoke(db, "someTitle");

どうやら関数はSQLなどに変換されていないようですが(どうすればよいでしょうか)、VS2010でブレークポイントを設定しても保持されません。

問題なく動作しますが、方法や理由がわかりません。そこでは正確に何が起こりますか?

4

2 に答える 2

2

あなたのDataConvert.ToThema()静的メソッドは、デフォルトのコンストラクターを持つ型のインスタンスを作成し、さまざまなプロパティを設定するだけですが、正しいですか? もしそうなら、それは以下とそれほど違いはありません:

(from th in elan.tbl_Thema
where th.Titel == title
select new Thema{ID=th.ThemaID, Titel=th.Titel, etc...}
).Single());

を呼び出すQueries.GetThemaByTitleと、クエリがコンパイルされます。(ちなみに、あなたがこれを呼んでいる方法は、実際にはプリコンパイルの恩恵を受けているかもしれませんし、そうでないかもしれません)。その「クエリ」は実際にはコード式ツリーであり、その一部のみがデータベースに送信される SQL コードを生成することを目的としています。

その他の部分は、データベースから返されたものを取得し、消費するために何らかの形に変換する IL コードを生成します。LINQ (EF または L2S) は、静的メソッド呼び出しを取得し、そこから IL を生成して、必要なことを実行できるほどスマートです。おそらく、内部delegateなどでそうしています。しかし、最終的には、上記の代入から生成されるものと (大きく) 異なる必要はありません。

ただし、これは返される型に関係なく発生することに注意してください。どこかで、DB 値を CLR オブジェクトに入れる IL コードが生成されています。それは、これらの式ツリーの別の部分です。


これらの式ツリーとそれらに関係するものをより詳細に確認したい場合は、掘り下げる必要がありますが、あなたの質問からそれがあなたが探しているものかどうかわかりません。

于 2011-04-10T14:39:06.287 に答える
1

まず、クエリをコンパイルするかどうかは重要ではないことを指摘しておきます。プリコンパイルしなくても、まったく同じ結果が得られます。

技術的には、アンドリューが指摘したように、この作業を行うことはそれほど複雑ではありません。LINQ式が評価されると、式ツリーが内部で構築されます。関数は、この式ツリーのノードとして表示されます。ここには魔法はありません。この式はL2SとL2Eの両方で記述でき、コンパイルされて正常に実行されます。これは、データベースに対して実際のSQLクエリを実際に実行しようとするまでです。ここから違いが始まります。L2Sはこのタスクをうまく実行しているようですが、L2EはNotSupportedExceptionで失敗し、ToThemaをストアクエリに変換する方法がわからないと報告しています。

では、内部で何が起こっているのでしょうか。L2Sでは、Andrewが説明したように、クエリコンパイラは、ストアクエリが実行されたのとは別に関数を実行できることを理解しています。そのため、関数への呼び出しをオブジェクト読み取りパイプラインに送信します(SQLから読み取られたデータは、呼び出しの結果として返されるオブジェクトに変換されます)。

Andrewが正しくなかったことは、静的メソッドの内部に何があるかが重要であるということです。そうは思わない。

デバッガーで関数にブレークポイントを設定すると、返された行ごとに1回呼び出されることがわかります。スタックトレースには「LightweightFunction」が表示されます。これは、実際には、メソッドが実行時に発行されたことを意味します。つまり、これがLinqtoSqlでどのように機能するかです。

LinqtoEntityチームは別のルートを進んでいるようです。L2EクエリからすべてのInvocationExpressionsを禁止することにした理由、理由はわかりません。おそらく、これらはパフォーマンス上の理由であるか、データリーダーの動作が異なる可能性があるため、SQL Serverだけでなく、すべての種類のプロバイダーをサポートする必要があるという事実である可能性があります。または、ほとんどの人は、それらの一部が返された行ごとに実行され、このオプションを閉じたままにすることを好むことに気付かないだろうと単純に考えました。

ただ私の考え。誰かがこれ以上の洞察を持っているなら、チャイムを入れてください!

于 2011-04-15T13:38:47.267 に答える