包括编译查询中的"离线"代码

mag*_*tic 6 .net c# linq-to-sql compiled-query

当我在我的编译查询中包含一个函数时,窗帘后面会发生什么,就像我在这里使用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;
    }
}
Run Code Online (Sandbox Code Playgroud)

并称之为这样

Thema th = Queries.GetThemaByTitle.Invoke(db, "someTitle");
Run Code Online (Sandbox Code Playgroud)

显然,该函数没有转换为SQL或其他东西(怎么可能),但是当我在VS2010中设置断点时它也不成立.

它没有问题,但我不明白为什么或为什么.究竟发生了什么?

And*_*ber 2

您的DataConvert.ToThema()静态方法只是创建一个具有默认构造函数的类型的实例,并设置各种属性,这是正确的吗?如果是这样,那么它与以下内容没有太大不同:

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

当您调用 时Queries.GetThemaByTitle,正在编译一个查询。(顺便说一句,您所说的方式实际上可能会或可能不会给您带来预编译的任何好处)。该“查询”实际上是一个代码表达式树,其中只有一部分用于生成发送到数据库的 SQL 代码。

它的其他部分将生成 IL 代码,该代码获取从数据库返回的内容并将其放入某种形式供您使用。LINQ(EF 或 L2S)足够智能,能够接受静态方法调用并从中生成 IL 来执行您想要的操作 - 也许它是通过内部delegate或某些类似的方法来执行此操作。但最终,它不需要与我上面替换生成的内容有(太大)不同。

但请注意,无论您返回的类型是什么,都会发生这种情况;某处正在生成 IL 代码,将 DB 值放入 CLR 对象中。这是表达式树的另一部分。


如果您想更详细地了解这些表达式树及其涉及的内容,我必须为您挖掘,但从您的问题中我不确定这是否是您正在寻找的内容。