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;
}
我 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;
}