如何让我的LINQ查询生成我期望的SQL语句?

时间:2015-04-17 13:32:29

标签: c# asp.net sql-server entity-framework where-clause

我有一个简单的网络表单,其中我有3个texboxes和一个带搜索按钮的下拉列表。

这是我根据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

2 个答案:

答案 0 :(得分:0)

尝试这样写:

(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 == ""))

答案 1 :(得分:0)

如果您以小步骤构建查询,这将会更加简单。

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>