LINQ TO SQL 动态查询

      有时候我们的应用程序可能会提供一个用户界面,用户可以使用该用户界面指定一个或多个谓词来筛选数据。这对于刚刚接触LINQ TO SQL的朋友来说可能比较费劲。相对会怀念SQL下的strWhere拼接的方便形式。其实这种情况下LINQ也有比较简单的实现方式。

      首先来看看案例界面


楚旋博客园

类似上图片,在LINQ TO SQL下实现动态条件查询!

本文提供二种方法:

 //此方法是 “一步步” 缩小 查询 的范围
        private void MethodA()
        {
            
using (NewCnqsqDataContext db = new NewCnqsqDataContext())
            {
                
//记录Linq to sql 最终执行的SQL语句
                StreamWriter sw = new StreamWriter("c:/testsql.txt");
                db.Log 
= sw;

                
//查询所有
                var query = from obj in db.QwqSubject orderby obj.suCreateDate descending select obj;
                
if (ddlSuType.SelectedValue != "-1")
                {
                    
//如果选择 增加 查询贴吧类型
                    query = from obj in query where obj.suType == Convert.ToInt32(ddlSuType.SelectedValue) orderby obj.suCreateDate descending select obj;
                }
                
if (ddlBigType.SelectedValue != "-1")
                {
                    
//如果选择 增加 查询帖子的类别
                    query = from obj in query where obj.suBigType == ddlBigType.SelectedValue orderby obj.suCreateDate descending select obj;
                }
                
if (txtSearch.Text.Trim() != "")
                {
                    
//如果有关键字 增加  查询标题中是否含有
                    query = from obj in query where obj.suTitle.Contains(txtSearch.Text.Trim()) orderby obj.suCreateDate descending select obj;
                }
                
//由于LINQ TO SQL采用延迟加载技术 所以不用担心 上面代码 在查询 4次 最终“聪明”的LINQ 会只执行一条SQL语句
                GridView1.DataSource = query;
                GridView1.DataBind();
                sw.Flush();
                sw.Close();
            }
        }

最终执行的SQL语句为:

SELECT [t0].[suId][t0].[suTitle][t0].[suUserId][t0].[suType][t0].[suCreateDate][t0].[suContent][t0].[suState][t0].[suInfo1][t0].[suInfo2][t0].[suBigType][t0].[suOrderBy][t0].[fromIp]
FROM [dbo].[QwqSubject] AS [t0]
WHERE ([t0].[suTitle] LIKE @p0AND ([t0].[suBigType] = @p1AND ([t0].[suType] = @p2)
ORDER BY [t0].[suCreateDate] DESC
-- @p0: Input NVarChar (Size = 4; Prec = 0; Scale = 0) [%写真%]
--
 @p1: Input NVarChar (Size = 2; Prec = 0; Scale = 0) [随便贴吧]
--
 @p2: Input Int (Size = 0; Prec = 0; Scale = 0) [1]
--
 Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30729.1

 

方法2

//动态LINQ 类似 “反射” 将字符串 按最终 LINQ TO SQL 的语义 执行
        private void MethodB()
        {
            
using (NewCnqsqDataContext db = new NewCnqsqDataContext())
            {
                
//记录Linq to sql 最终执行的SQL语句
                StreamWriter sw = new StreamWriter("c:/testsql2.txt");
                db.Log 
= sw;
                
string strWhere = "1==1 ";//默认查询所有

                
if (ddlSuType.SelectedValue != "-1")
                {
                    strWhere 
+= " and suType==" + Convert.ToInt32(ddlSuType.SelectedValue) + "";
                }
                
if (ddlBigType.SelectedValue != "-1")
                {
                    strWhere 
+= " and suBigType==\"" + ddlBigType.SelectedValue + "\"";
                }
                
if (txtSearch.Text.Trim() != "")
                {
                    strWhere 
+= " and suTitle.Contains(\"" + txtSearch.Text.Trim() + "\")";
                }

                
//显示排序 以及 查寻指定列 可以直接 db.QwqSubject.Where(strWhere) 取结果 如果不需要排序 和 指定列
                var query = db.QwqSubject.Where(strWhere).OrderBy("suCreateDate desc,suBigType asc").Select("New(suType, suBigType,suTitle)");
                
                GridView1.DataSource 
= query;
                GridView1.DataBind();
                sw.Flush();
                sw.Close();
            }
        }

方法2生成的SQL语句为:

SELECT [t0].[suType][t0].[suBigType][t0].[suTitle]
FROM [dbo].[QwqSubject] AS [t0]
WHERE ([t0].[suType] = @p0AND ([t0].[suTitle] LIKE @p1)
ORDER BY [t0].[suCreateDate] DESC[t0].[suBigType]
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [2]
--
 @p1: Input NVarChar (Size = 4; Prec = 0; Scale = 0) [%写真%]
--
 Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30729.1

注意:要使上述方法编译通过,需要引入using System.Linq.Dynamic;命名空间。该命名空间系统中默认没有,但微软在VS2008安装文件夹中可以找到

C:\Program Files\Microsoft Visual Studio 9.0\Samples\2052\CSharpSamples.zip 解压出来后在LinqSamples可以找到。如果找不到该压缩包,可以从微软官方http://code.msdn.microsoft.com/csharpsamples/Release/ProjectReleases.aspx?ReleaseId=8进行下载

官方提供的Dynamic.cs采用了C#新特性 扩展了DynamicQueryable的固有函数。使得系统中原有的where,orderby等可以直接将string作为参数,然后再把传入的字符串进行分析,最终通过System.Linq.Expressions.Expression来实现动态Lambda 。我们也可以更好的体会到扩展方法的好处和强大。

      另外网上还有相对“正统”的解决方法 使用表达式树来解决。但我个人认为这种方式显得太不友好。

posted on 2009-07-16 22:17  冯岩  阅读(4861)  评论(5编辑  收藏  举报

导航