Linq to SQL Microsoft ReferenceSource 中的源代码

Linq to SQL Source in Microsoft ReferenceSource

我 google 并查看 ReferenceSource 但我找不到 LINQ to SQL 的来源,其中 LINQ 查询转换为 SQL 语句。有知道的人吗?

例如:

from item in Users
select item

转换为:

SELECT [t0].[UserID], [t0].[Username], [t0].[FirstName], [t0].[LastName], [t0].[IsSuperUser], [t0].[AffiliateId], [t0].[Email], [t0].[DisplayName], [t0].[UpdatePassword]
FROM [Users] AS [t0]

怎么样?我想在 DotnetFramwork source.

中查看此行为的来源

您可以使用 sql server management studio 附加一个 sql 分析器来了解确切的查询转换。

我相信正在寻找的 class 是 SqlFormatter class. It will take a tree of SqlNode 并使用访问者将其转换为数据库查询字符串。

节点树本身似乎是由 SqlFactory class 中的工厂方法创建的。

我使用了 DbCommand 数据上下文。它需要一个 IQueryable。 System.Data.Linq.DataContext.GetCommand(System.Linq.IQueryable)

总结: 表示要针对数据源执行的 SQL 语句或存储过程。为表示命令的特定于数据库的 classes 提供基础 class。

public void GetSqlCommand()
{
    const string sc2 = @"Server=SQLServerName;Database=DatabaseName;Trusted_Connection=True;";

    using (var dc = new DataContext(sc2))
    {
        var query = dc.GetTable<Users>()
            .Join(dc.GetTable<Phone>(),
                x => x.UserId,
                y => y.LastUserId,
                (x, y) => new { User = x, Phone = y }).Select(x => x);

            DbCommand command = dc.GetCommand(query);

            Assert.IsNotNull(command.CommandText);
    }
}

然后它会给你这样的东西

SELECT [t0].[UserId], [t0].[Login], [t0].[FullName], [t0].[LastUserId], [t0].[LastDateTime], [t1].[PhoneId], [t1].[PhoneNumber], [t1].[LastUserId] AS [LastUserId2], [t1].[LastDateTime] AS [LastDateTime2]
FROM [dbo].[Users] AS [t0]
INNER JOIN [dbo].[Phone] AS [t1] ON ([t0].[UserId]) = [t1].[LastUserId]

更新您似乎需要框架用于从查询构建 SQL 的代码。 这是 SQLProvider 的 MSFT 参考代码的 link 我认为您可以在其中找到答案。 SQLProvider

看看这个方法,它 returns 您传递的查询表达式的查询信息。 查询信息具有我上面提到的结果 CommandText。

internal QueryInfo[] BuildQuery(Expression query, SqlNodeAnnotations annotations) {.. calls the private BuildQuery..}

private QueryInfo[] BuildQuery(ResultShape resultShape, Type resultType, SqlNode node, ReadOnlyCollection<Me.SqlParameter> parentParameters, SqlNodeAnnotations annotations) {...}

......

internal class QueryInfo {
    SqlNode query;
    string commandText;
    ReadOnlyCollection<SqlParameterInfo> parameters;
    ResultShape resultShape;
    Type resultType;

    internal QueryInfo(SqlNode query, string commandText, ReadOnlyCollection<SqlParameterInfo> parameters, ResultShape resultShape, Type resultType) {
        this.query = query;
        this.commandText = commandText;
        this.parameters = parameters;
        this.resultShape = resultShape;
        this.resultType = resultType;
    }
    internal SqlNode Query {
        get { return this.query; }
    }
    internal string CommandText {
        get { return this.commandText; }
    }
    internal ReadOnlyCollection<SqlParameterInfo> Parameters {
        get { return this.parameters; }
    }
    internal ResultShape ResultShape {
        get { return this.resultShape; }
    }
    internal Type ResultType {
        get { return this.resultType; }
    }
}

您会看到 GetCommand 还调用 Build Query 方法生成 SQL 然后从第一个查询中获取命令文本

DbCommand IProvider.GetCommand(Expression query) 
{
    this.CheckDispose();
    this.CheckInitialized();
    if (query == null) {
        throw Error.ArgumentNull("query");
    }
    this.InitializeProviderMode();
    SqlNodeAnnotations annotations = new SqlNodeAnnotations();
    QueryInfo[] qis = this.BuildQuery(query, annotations);
    QueryInfo qi = qis[qis.Length - 1];
    DbCommand cmd = this.conManager.Connection.CreateCommand();
    cmd.CommandText = qi.CommandText;
    cmd.Transaction = this.conManager.Transaction;
    cmd.CommandTimeout = this.commandTimeout;
    AssignParameters(cmd, qi.Parameters, null, null);
    return cmd;
}