querybuilder排序_SelectQueryBuilder的⽤法SelectQueryBuilder类允许在你的代码中建⽴复杂的SQL语句和命令。它也能帮助于避免SQL注⼊式攻击。
SelectQueryBuilder类包含了许多属性和⽅法,你能很容易地在Select语句中使⽤它们。⼀旦调⽤BuildQuery() 和BuildCommand()⽅法,它能提供⼀种更好的旧的“字符串查询“或可以使⽤命令参数的DbCommand对象来查询数据。
不安全的旧⽅法:
下⾯的代码阐明了以前建⽴SELECT语句的⽅法,它使⽤许多类变量来说明应该使⽤那种连接操作(WHERE,或者OR),同时也给你的数据库带来了可能的SQL注⼊式攻击。荒唐无稽
string statement = "SELECT TOP" + maxRecords + "* FROM Customers";string whereConcatenator = "WHERE";if (companyNameTextBox.Text.Length > 0)
{
statement+=whereConcatenator;
statement+= "CompanyName like '" + companyNameTextBox.Text + "%'";
whereConcatenator= "AND";
}if (cityTextBox.Text.Length > 0)
{
statement+=whereConcatenator;
statement+= "City like '" + cityTextBox.Text + "%'";
whereConcatenator= "AND";
}if (countryComboBox.SelectedItem != null)
{
statement+=whereConcatenator;
statement+= "Country = '" + countryComboBox.SelectedItem + "'";
whereConcatenator= "AND";
江南水乡古镇
}
我相信上⾯的代码对你来说是⾮常熟悉的,你可能在过去的⼗多年⼀直是这样使⽤的,或者你曾经编码过数据库驱动的搜索功能。让我告诉你这种思想:这种查询你的数据库的⽅法不能再使⽤了,它是难看的也是不安全的。
SelectQueryBuilder⽅式的代码
同样的查询能够使⽤SelectQueryBuilder类建⽴。
SelectQueryBuilder query = new SelectQueryBuilder();
query.SelectFromTable("Customers");
query.SelectAllColumns();
query.TopRecords = maxRecords;
if (companyNameTextBox.Text.Length > 0)
query.AddWhere("CompanyName", Comparison.Like,companyNameTextBox.Text + "%");
if (cityTextBox.Text.Length > 0)
query.AddWhere("City", Comparison.Like,
cityTextBox.Text + "%");
if (countryComboBox.SelectedItem != null)
query.AddWhere("Country", Comparison.Equals,
countryComboBox.SelectedItem);
string statement = query.BuildQuery();
// or, have a DbCommand object built
// for even more safety against SQL Injection attacks:
query.SetDbProviderFactory(
DbProviderFactories.GetFactory(
"System.Data.SqlClient"));
DbCommand command = query.BuildCommand();
你能看到,这种⽅式⽐直接使⽤连接字符串更直观。考虑到第⼀个例⼦SQL注⼊的危险,通过SelectQueryBuilder建⽴的SELECT查询是⾮常安全的,并不⽤担⼼使⽤的TextBoxs中的内容。事实上它也⾮常简单!
使⽤SQL函数
如果你想在你的查询中使⽤SQL函数,你能使⽤SqlLiteral类来打包函数的调⽤。说明这个类能作什么的最好⽅式就是给你显⽰⼀⼩段代码例⼦:
SelectQueryBuilder query = new SelectQueryBuilder();
query.SelectFromTable("Orders");
query.AddWhere("OrderDate", Comparison.LessOrEquals,new SqlLiteral("getDate()"));
如果我们没有打包getDate()函数调⽤到SqlLiteral类中,建⽴的查询就会产⽣WHERE⼦ 句:OrderDate
<=’getDate()’。当然,我们希望在语句中的这个函数没有被单引号包围。这时SqlLiteral就可以派上⽤场 了:它直接拷贝字符串到输出,并没有把它格式化成字符串。现在的输出WHERE⼦句应当是OrderDate<=getDate()!
查询中使⽤JOINs
要创建到其它表的JOINs,你能使⽤AddJoin⽅法。下⾯的代码显⽰了如何创建⼀个从Ordres表到Customers表的INNER JOIN。
感恩老师黑板报
SelectQueryBuilder query = new SelectQueryBuilder();
query.SelectFromTable("Orders");
query.AddJoin(JoinType.InnerJoin,"Customers", "CustomerID",Comparison.Equals,"Orders", "CustomerID");
query.AddWhere("Customers.City",Comparison.Equals, "London");
宽窄巷子这段代码选择所有居住在London的客户的订单。⼀旦调⽤了BuildQuery⽅法,就会产⽣下⾯的SQL语句:
SELECT Orders.*
FROM Orders
INNER JOIN Customers ON Orders.CustomerID = Customers.CustomerID
WHERE (Customers.City = 'London')
注意到缺省的查询只会建⽴所选择的表的lects * 语句(这个例⼦中的Orders.*)。如果你也想选择连接表的列的话,你必须得显式地选择它们。你能通⽤调⽤query.SelectColumns(“Orders.*”,”Customers.*”)。
建⽴计算查询
如果你想对你的数据库执⾏⼀个计算查询。你能使⽤SelectCount⽅法如同下⾯显⽰的:
Query.SelectCount();
在更加复杂的计算查询中,你可能想使⽤GROUP BY语句。看⼀下下⾯的例⼦,它显⽰了如何使⽤GroupBy和AddHaving⽅法。
SelectQueryBuilder query = new SelectQueryBuilder();
query.SelectColumns("count(*) AS Count", "ShipCity");
query.SelectFromTable("Orders");
query.GroupBy("ShipCity");
query.AddHaving("ShipCity", Comparison.NotEquals, "Amsterdam");
query.AddOrderBy("count(*)", Sorting.Descending);
上⾯的代码选择了每个城市的订单数,并⽤订单数⽬排序,不考虑来⾃制Amsterdam的订单,BuildQuery⽅法的输出结果应当是:
SELECT count(*) AS Count, ShipCity
FROM Orders
GROUP BY ShipCity
HAVING (ShipCity <> 'Amsterdam')
ORDER BY count(*) DESC
复杂的Where语句
如果你曾经⽤过微软的Access或SQL Server的内置的查询⽣成器的话,是否惊讶你能建⽴和代码⼀样的包含多层ANDs和Ors,并没有关⼼()符号的位置的查询?是的?我也能!
你能使⽤SelectQueryBuilder类实现!你能加多层的WHERE语句到你的查询。缺省,所有对query.AddWhere的调⽤被 放在查询的第⼀层上。你可以把它⽐作SQL Server查询⽣成器的’Criteria’列;第⼆、三、四层等相应地对应于’Or…’列。
看⼀下下⾯的SQL Server查询⽣成器的快照,通过它我能快速地把简单的假的SELECT语句放在⼀起来:
如你看到的,我创建⼀个查询,它选择所有在1-1-2005⽇期之前的客户’VINET’的订单,和所有30-6-2004⽇期之前或1-1-2006⽇期之后的客户’TOMSP’的订单(请不要问为什么有⼈想查询某个⼈的订单,这仅仅是⼀个 例⼦)。这个查询能够建⽴:
SelectQueryBuilder query = new SelectQueryBuilder();
query.SelectFromTable("Orders");
// Add 'Criteria' column to level 1
query.AddWhere("CustomerID", Comparison.Equals,"VINET", 1);
query.AddWhere("OrderDate", Comparison.LessThan,new DateTime(2005,1,1), 1);
// Add first 'Or...' column to level 2
query.AddWhere("CustomerID", Comparison.Equals, "TOMSP", 2);
query.AddWhere("OrderDate", Comparison.LessThan,new DateTime(2004,6,30), 2);
// Add cond 'Or...' column to level 3
query.AddWhere("CustomerID", Comparison.Equals,"TOMSP", 3);
query.AddWhere("OrderDate", Comparison.GreaterThan,new DateTime(2006,1,1), 3);
当调⽤ BuildQuery时,所有定义的层将被OR到⼀起,⼏乎和SQL Server⽣成的⼀样。
如果你到所产⽣的语句接近⼀样时,想让查询更复杂,你可能会说“我的放两个随后的语句⼀起放在⼀个语句中,在两个⽇期间使⽤OR”。你能够这样作。在SQL Server查询⽣成器中,这个查询看起来像:
同样,它也可能使⽤SelectQueryBuilder通过创建’嵌套的WHERE⼦句’来实现。
SelectQueryBuilder query = new SelectQueryBuilder();
query.SelectFromTable("Orders");
// Add 'Criteria' column to level 1
query.AddWhere("CustomerID", Comparison.Equals, "VINET", 1);
query.AddWhere("OrderDate", Comparison.LessThan,水稻简笔画
new DateTime(2005,1,1), 1);
// Add 'Or...' column to level 2
query.AddWhere("CustomerID",
Comparison.Equals, "TOMSP", 2);
豆腐的制作流程// Add the date lection clau
WhereClau clau =query.AddWhere("OrderDate", Comparison.LessThan,
new DateTime(2004,6,30), 2);
// Add a nested clau to the captured clau
clau.AddClau(LogicOperator.Or,
Comparison.GreaterThan, new DateTime(2006,1,1));
欢乐垂钓注意到我⽤了⼀个WhereClau对象,它由AddWhere调⽤返回。接着调⽤clau.AddClau创建⼀个嵌套的⼦句柄,并且选择通过指定LogicOperator.Or来把它OR到第⼀个⼦句上。所产⽣的语句如下:
SELECT Orders.*
FROM Orders
WHERE
(
(CustomerID = 'VINET')
AND (OrderDate < '2005/01/01 12:00:00')
)
OR
(
(CustomerID = 'TOMSP')
AND (OrderDate < '2004/06/30 12:00:00' OR
OrderDate > '2006/01/01 12:00:00')
哥哥和我
)