如何让我的 LINQ 查询生成我期望的 SQL 语句?
How do I get my LINQ Query to generate the SQL statement I expect?
我有一个简单的 Web 表单,其中有 3 个文本框和一个带有搜索按钮的下拉列表。
这是我根据从 4 个控件中选择的输入过滤 EF(4.0) 上下文的代码:
string mFormId = ddlTransValueSearchFormId.SelectedItem.Text.ToString().Trim();
string mControlId = ddlTransValueSearchControlId.SelectedItem.Text.ToString().Trim();
int mTransCategoryId;
try
{
mTransCategoryId = Int32.Parse(ddlTransValueSearchCategoryId.SelectedItem.Value.ToString());
}
catch(Exception ex)
{
throw ex;
}
string mDefaultTransValue = tbTransValueSearchDefaultValue.Text.ToString().Trim();
我的 LINQ 查询
TranslationEntity efSchema = new TranslationEntity();
gvTransValues.DataSource = (from defaultValue in efSchema.TRANS_VALUES
.Include("TRANS_CATEGORY")
where (
mFormId == "" ? 1 == 1 : defaultValue.FormId.Contains(mFormId)
&& mControlId == "" ? 1 == 1 : defaultValue.ControlId.Contains(mControlId)
&& mTransCategoryId == -1 ? 1 == 1 : defaultValue.TransCategoryId == mTransCategoryId
&& mDefaultTransValue == "" ? 1 == 1 : defaultValue.DefaultTranValue.Contains(mDefaultTransValue)
)
select new
{
TranValueId = defaultValue.TranValueId,
FormId = defaultValue.FormId,
ControlId = defaultValue.ControlId,
TransCategoryId = defaultValue.TransCategoryId,
CategoryName = defaultValue.TRANS_CATEGORY.CategoryName,
DefaultTranValue = defaultValue.DefaultTranValue,
});
gvTransValues.DataBind();
生成的SQL语句
使用探查器,这是生成的 SQL 查询:
declare @p__linq__0 nvarchar(4000),@p__linq__1 nvarchar(4000),@p__linq__2 nvarchar(4000),@p__linq__3 nvarchar(4000),@p__linq__4 int,@p__linq__5 int,@p__linq__6 nvarchar(4000),@p__linq__7 nvarchar(4000)
SELECT @p__linq__0=N'',@p__linq__1=N'%%',@p__linq__2=N'',@p__linq__3=N'%%',@p__linq__4=1,@p__linq__5=1,@p__linq__6=N'cat',@p__linq__7=N'%cat%'
SELECT
[Extent1].[TRAN_VALUE_ID] AS [TRAN_VALUE_ID],
[Extent1].[FORM_ID] AS [FORM_ID],
[Extent1].[CONTROL_ID] AS [CONTROL_ID],
[Extent1].[TRANS_CATEGORY_ID] AS [TRANS_CATEGORY_ID],
[Extent2].[CATEGORY_NAME] AS [CATEGORY_NAME],
[Extent1].[DEFAULT_TRAN_VALUE] AS [DEFAULT_TRAN_VALUE]
FROM [dbo].[TRANS_VALUES] AS [Extent1]
LEFT OUTER JOIN [dbo].[TRANS_CATEGORY] AS [Extent2] ON [Extent1].[TRANS_CATEGORY_ID] = [Extent2].[TRANS_CATEGORY_ID]
WHERE
(CASE
WHEN (N'' = @p__linq__0) THEN cast(1 as bit)
WHEN (([Extent1].[FORM_ID] LIKE @p__linq__1 ESCAPE N'~') AND (N'' = @p__linq__2)) THEN cast(1 as bit)
WHEN (([Extent1].[CONTROL_ID] LIKE @p__linq__3 ESCAPE N'~') AND (-1 = @p__linq__4)) THEN cast(1 as bit)
WHEN (([Extent1].[TRANS_CATEGORY_ID] = @p__linq__5) AND (N'' = @p__linq__6)) THEN cast(1 as bit)
WHEN ([Extent1].[DEFAULT_TRAN_VALUE] LIKE @p__linq__7 ESCAPE N'~') THEN cast(1 as bit)
WHEN ( NOT ([Extent1].[DEFAULT_TRAN_VALUE] LIKE @p__linq__7 ESCAPE N'~')) THEN cast(0 as bit)
END) = 1
这不是我想要的。无论参数值如何,EF 生成脚本的方式都是从数据库返回所有行。
这里出了什么问题?
我要的SQL语句
事实上,就 SQL 服务器而言,我需要并认为最佳的是让 EF 生成这种查询。
SELECT
[Extent1].[TRAN_VALUE_ID] AS [TRAN_VALUE_ID],
[Extent1].[FORM_ID] AS [FORM_ID],
[Extent1].[CONTROL_ID] AS [CONTROL_ID],
[Extent1].[TRANS_CATEGORY_ID] AS [TRANS_CATEGORY_ID],
[Extent2].[CATEGORY_NAME] AS [CATEGORY_NAME],
[Extent1].[DEFAULT_TRAN_VALUE] AS [DEFAULT_TRAN_VALUE]
FROM [dbo].[TRANS_VALUES] AS [Extent1]
LEFT OUTER JOIN [dbo].[TRANS_CATEGORY] AS [Extent2] ON [Extent1].[TRANS_CATEGORY_ID] = [Extent2].[TRANS_CATEGORY_ID]
WHERE
ISNULL([Extent1].[FORM_ID],N'') LIKE '%' + COALESCE(@p__linq__0,[Extent1].[FORM_ID],N'') + '%'
AND ISNULL([Extent1].[CONTROL_ID],N'') LIKE '%' + COALESCE(@p__linq__1,[Extent1].[CONTROL_ID],N'') + '%'
AND ISNULL([Extent1].[TRANS_CATEGORY_ID],-1) = COALESCE(@p__linq__2,[Extent1].[TRANS_CATEGORY_ID],-1)
AND ISNULL([Extent1].[DEFAULT_TRAN_VALUE],N'') LIKE '%' + COALESCE(@p__linq__3,[Extent1].[DEFAULT_TRAN_VALUE],N'') + '%'
go
试试这样写:
(from defaultValue in efSchema.TRANS_VALUES
.Include("TRANS_CATEGORY")
where (defaultValue.FormId.Contains(mFormId) || mFormId == "")
&& (defaultValue.ControlId.Contains(mControlId) || mControlId == "")
&& (defaultValue.TransCategoryId.Contains(mTransCategoryId) || mTransCategoryId == "")
&& (defaultValue.DefaultTranValue.Contains(mDefaultTransValue) || mDefaultTransValue == ""))
如果您逐步构建查询,这会简单得多。
var query = efSchema.TRANS_VALUES.Include("TRANS_CATEGORY");
if(!string.IsNullOrEmpty(mFormId))
{
query = query.Where(defaultValue => defaultValue.FormId.Contains(mFormId));
}
if(!string.IsNullOrEmpty(mControlId))
{
query = query.Where(defaultValue => defaultValue.ControlId.Contains(mControlId));
}
if(mTransCategoryId != -1)
{
query = query.Where(defaultValue => defaultValue.TransCategoryId == mTransCategoryId);
}
if(!string.IsNullOrEmpty(mDefaultTransValue))
{
query = query.Where(defaultValue => defaultValue.DefaultTransValue.Contains(mDefaultTransValue));
}
gvTransValues.DataSource = query.Select(defaultValue => new
{
TranValueId = defaultValue.TranValueId,
FormId = defaultValue.FormId,
ControlId = defaultValue.ControlId,
TransCategoryId = defaultValue.TransCategoryId,
CategoryName = defaultValue.TRANS_CATEGORY.CategoryName,
DefaultTranValue = defaultValue.DefaultTranValue,
});
(我认为它应该像这样工作,但您可能必须将 query
的初始类型指定为 IQueryable<YOURTYPE>
)
我有一个简单的 Web 表单,其中有 3 个文本框和一个带有搜索按钮的下拉列表。
这是我根据从 4 个控件中选择的输入过滤 EF(4.0) 上下文的代码:
string mFormId = ddlTransValueSearchFormId.SelectedItem.Text.ToString().Trim();
string mControlId = ddlTransValueSearchControlId.SelectedItem.Text.ToString().Trim();
int mTransCategoryId;
try
{
mTransCategoryId = Int32.Parse(ddlTransValueSearchCategoryId.SelectedItem.Value.ToString());
}
catch(Exception ex)
{
throw ex;
}
string mDefaultTransValue = tbTransValueSearchDefaultValue.Text.ToString().Trim();
我的 LINQ 查询
TranslationEntity efSchema = new TranslationEntity();
gvTransValues.DataSource = (from defaultValue in efSchema.TRANS_VALUES
.Include("TRANS_CATEGORY")
where (
mFormId == "" ? 1 == 1 : defaultValue.FormId.Contains(mFormId)
&& mControlId == "" ? 1 == 1 : defaultValue.ControlId.Contains(mControlId)
&& mTransCategoryId == -1 ? 1 == 1 : defaultValue.TransCategoryId == mTransCategoryId
&& mDefaultTransValue == "" ? 1 == 1 : defaultValue.DefaultTranValue.Contains(mDefaultTransValue)
)
select new
{
TranValueId = defaultValue.TranValueId,
FormId = defaultValue.FormId,
ControlId = defaultValue.ControlId,
TransCategoryId = defaultValue.TransCategoryId,
CategoryName = defaultValue.TRANS_CATEGORY.CategoryName,
DefaultTranValue = defaultValue.DefaultTranValue,
});
gvTransValues.DataBind();
生成的SQL语句
使用探查器,这是生成的 SQL 查询:
declare @p__linq__0 nvarchar(4000),@p__linq__1 nvarchar(4000),@p__linq__2 nvarchar(4000),@p__linq__3 nvarchar(4000),@p__linq__4 int,@p__linq__5 int,@p__linq__6 nvarchar(4000),@p__linq__7 nvarchar(4000)
SELECT @p__linq__0=N'',@p__linq__1=N'%%',@p__linq__2=N'',@p__linq__3=N'%%',@p__linq__4=1,@p__linq__5=1,@p__linq__6=N'cat',@p__linq__7=N'%cat%'
SELECT
[Extent1].[TRAN_VALUE_ID] AS [TRAN_VALUE_ID],
[Extent1].[FORM_ID] AS [FORM_ID],
[Extent1].[CONTROL_ID] AS [CONTROL_ID],
[Extent1].[TRANS_CATEGORY_ID] AS [TRANS_CATEGORY_ID],
[Extent2].[CATEGORY_NAME] AS [CATEGORY_NAME],
[Extent1].[DEFAULT_TRAN_VALUE] AS [DEFAULT_TRAN_VALUE]
FROM [dbo].[TRANS_VALUES] AS [Extent1]
LEFT OUTER JOIN [dbo].[TRANS_CATEGORY] AS [Extent2] ON [Extent1].[TRANS_CATEGORY_ID] = [Extent2].[TRANS_CATEGORY_ID]
WHERE
(CASE
WHEN (N'' = @p__linq__0) THEN cast(1 as bit)
WHEN (([Extent1].[FORM_ID] LIKE @p__linq__1 ESCAPE N'~') AND (N'' = @p__linq__2)) THEN cast(1 as bit)
WHEN (([Extent1].[CONTROL_ID] LIKE @p__linq__3 ESCAPE N'~') AND (-1 = @p__linq__4)) THEN cast(1 as bit)
WHEN (([Extent1].[TRANS_CATEGORY_ID] = @p__linq__5) AND (N'' = @p__linq__6)) THEN cast(1 as bit)
WHEN ([Extent1].[DEFAULT_TRAN_VALUE] LIKE @p__linq__7 ESCAPE N'~') THEN cast(1 as bit)
WHEN ( NOT ([Extent1].[DEFAULT_TRAN_VALUE] LIKE @p__linq__7 ESCAPE N'~')) THEN cast(0 as bit)
END) = 1
这不是我想要的。无论参数值如何,EF 生成脚本的方式都是从数据库返回所有行。
这里出了什么问题?
我要的SQL语句
事实上,就 SQL 服务器而言,我需要并认为最佳的是让 EF 生成这种查询。
SELECT
[Extent1].[TRAN_VALUE_ID] AS [TRAN_VALUE_ID],
[Extent1].[FORM_ID] AS [FORM_ID],
[Extent1].[CONTROL_ID] AS [CONTROL_ID],
[Extent1].[TRANS_CATEGORY_ID] AS [TRANS_CATEGORY_ID],
[Extent2].[CATEGORY_NAME] AS [CATEGORY_NAME],
[Extent1].[DEFAULT_TRAN_VALUE] AS [DEFAULT_TRAN_VALUE]
FROM [dbo].[TRANS_VALUES] AS [Extent1]
LEFT OUTER JOIN [dbo].[TRANS_CATEGORY] AS [Extent2] ON [Extent1].[TRANS_CATEGORY_ID] = [Extent2].[TRANS_CATEGORY_ID]
WHERE
ISNULL([Extent1].[FORM_ID],N'') LIKE '%' + COALESCE(@p__linq__0,[Extent1].[FORM_ID],N'') + '%'
AND ISNULL([Extent1].[CONTROL_ID],N'') LIKE '%' + COALESCE(@p__linq__1,[Extent1].[CONTROL_ID],N'') + '%'
AND ISNULL([Extent1].[TRANS_CATEGORY_ID],-1) = COALESCE(@p__linq__2,[Extent1].[TRANS_CATEGORY_ID],-1)
AND ISNULL([Extent1].[DEFAULT_TRAN_VALUE],N'') LIKE '%' + COALESCE(@p__linq__3,[Extent1].[DEFAULT_TRAN_VALUE],N'') + '%'
go
试试这样写:
(from defaultValue in efSchema.TRANS_VALUES
.Include("TRANS_CATEGORY")
where (defaultValue.FormId.Contains(mFormId) || mFormId == "")
&& (defaultValue.ControlId.Contains(mControlId) || mControlId == "")
&& (defaultValue.TransCategoryId.Contains(mTransCategoryId) || mTransCategoryId == "")
&& (defaultValue.DefaultTranValue.Contains(mDefaultTransValue) || mDefaultTransValue == ""))
如果您逐步构建查询,这会简单得多。
var query = efSchema.TRANS_VALUES.Include("TRANS_CATEGORY");
if(!string.IsNullOrEmpty(mFormId))
{
query = query.Where(defaultValue => defaultValue.FormId.Contains(mFormId));
}
if(!string.IsNullOrEmpty(mControlId))
{
query = query.Where(defaultValue => defaultValue.ControlId.Contains(mControlId));
}
if(mTransCategoryId != -1)
{
query = query.Where(defaultValue => defaultValue.TransCategoryId == mTransCategoryId);
}
if(!string.IsNullOrEmpty(mDefaultTransValue))
{
query = query.Where(defaultValue => defaultValue.DefaultTransValue.Contains(mDefaultTransValue));
}
gvTransValues.DataSource = query.Select(defaultValue => new
{
TranValueId = defaultValue.TranValueId,
FormId = defaultValue.FormId,
ControlId = defaultValue.ControlId,
TransCategoryId = defaultValue.TransCategoryId,
CategoryName = defaultValue.TRANS_CATEGORY.CategoryName,
DefaultTranValue = defaultValue.DefaultTranValue,
});
(我认为它应该像这样工作,但您可能必须将 query
的初始类型指定为 IQueryable<YOURTYPE>
)