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语句为:
FROM [dbo].[QwqSubject] AS [t0]
WHERE ([t0].[suTitle] LIKE @p0) AND ([t0].[suBigType] = @p1) AND ([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
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语句为:
FROM [dbo].[QwqSubject] AS [t0]
WHERE ([t0].[suType] = @p0) AND ([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 。我们也可以更好的体会到扩展方法的好处和强大。
另外网上还有相对“正统”的解决方法 使用表达式树来解决。但我个人认为这种方式显得太不友好。