在 C#/.NET3.5 中构造动态 sql 查询的最佳方式?
Posted
技术标签:
【中文标题】在 C#/.NET3.5 中构造动态 sql 查询的最佳方式?【英文标题】:Best way of constructing dynamic sql queries in C#/.NET3.5? 【发布时间】:2008-09-15 13:44:19 【问题描述】:我目前正在进行的一个项目涉及重构一个 C# Com 对象,该对象用作某些 Sql 2005 数据库的数据库访问层。
现有代码的作者使用字符串和许多 if 语句手动构建了所有 sql 查询,以构建相当复杂的 sql 语句(~10 个连接,>10 个子选择,~15-25 个条件和 GroupBy) .基表始终是同一个,但连接、条件和分组的结构取决于传递给我的类/方法的一组参数。
像这样构建 sql 查询确实有效,但它显然不是一个非常优雅的解决方案(而且也很难阅读/理解和维护)......我可以自己编写一个简单的“querybuilder”,但我是很确定我不是第一个遇到这种问题的人,因此我的问题是:
您如何构建数据库查询? C# 是否提供了一种简单的方法来动态构建查询?【问题讨论】:
【参考方案1】:我使用 C# 和 Linq 做了类似的事情来过滤用户输入的日志条目(参见 Conditional Linq Queries):
IQueryable<Log> matches = m_Locator.Logs;
// Users filter
if (usersFilter)
matches = matches.Where(l => l.UserName == comboBoxUsers.Text);
// Severity filter
if (severityFilter)
matches = matches.Where(l => l.Severity == comboBoxSeverity.Text);
Logs = (from log in matches
orderby log.EventTime descending
select log).ToList();
编辑:直到最后一条语句中的 .ToList() 才执行查询。
【讨论】:
一堆IF语句怎么算动态查询? IQueryable除非执行时间真的很重要,否则我会考虑重构(经常)倾向于找到通往数据层并进入数以万计的存储过程的业务逻辑。在可维护性、可编辑性和可附加性方面,我总是尝试(作为 C# 程序员)将代码提升到业务层。
尝试整理别人的 8000 行 SQL 脚本不是我最喜欢的任务。
:)
//W
【讨论】:
【参考方案3】:LINQ 是要走的路。
【讨论】:
【参考方案4】:这就是我的做法:
public IQueryable<ClientEntity> GetClients(Expression<Func<ClientModel, bool>> criteria)
return (
from model in Context.Client.AsExpandable()
where criteria.Invoke(model)
select new Ibfx.AppServer.Imsdb.Entities.Client.ClientEntity()
Id = model.Id,
ClientNumber = model.ClientNumber,
NameFirst = model.NameFirst,
//more propertie here
);
您传入的 Expression 参数将是您将使用不同的 WHERE 子句、JOINS 等构建的动态查询。此表达式将在运行时调用并给你你所需要的。
这是一个如何调用它的示例:
public IQueryable<ClientEntity> GetClientsWithWebAccountId(int webAccountId)
var criteria = PredicateBuilder.True<ClientModel>();
criteria = criteria.And(c => c.ClientWebAccount.WebAccountId.Equals(webAccountId));
return GetClients(criteria);
【讨论】:
【参考方案5】:如果您可以将其实现为参数化存储过程并在数据库中对其进行优化,而不是在运行时通过 LINQ 或 ORM 动态生成 SQL,那么值得考虑。通常这会表现得更好。我知道它有点过时,但有时它是最有效的方法。
【讨论】:
是的,我们已经对此进行了研究,但它并没有真正起作用,因为我们的查询变化很大......【参考方案6】:我了解 Linq 的潜力,但我还没有看到有人尝试对 Ben 建议的复杂性进行 Linq 查询
相当复杂的 sql 语句(~10 个连接,>10 个子选择,~15-25 个 where 条件和 GroupBy)
有没有人有大型 Linq 查询的示例,以及对其可管理性的任何评论?
【讨论】:
【参考方案7】:Linq to SQL 与 System.Linq.Dynamic 一起带来了一些不错的可能性。
我在这里发布了几个示例代码 sn-ps: http://blog.huagati.com/res/index.php/2008/06/23/application-architecture-part-2-data-access-layer-dynamic-linq
...这里: http://episteme.arstechnica.com/eve/forums/a/tpc/f/6330927813/m/717004553931?r=777003863931#777003863931
【讨论】:
【参考方案8】:我来晚了,没有机会投票,但有一个我没有考虑过的很好的解决方案:过程/函数与 linq-to-object 的组合。我想还是 to-xml 或 to-datatable。
我在这种情况下就遇到过这种情况,它有一个庞大的动态构建查询,这是一项令人印象深刻的成就,但其复杂性却使维护工作成为一场噩梦。我有这么多绿色的cmets来帮助后来不得不来理解它的可怜的树液。我使用的是经典的 asp,所以我几乎没有其他选择。
从那以后我所做的就是结合函数/过程和linq。通常总复杂度小于尝试在一个地方做的复杂度。将您的一些标准传递给 UDF,这变得更易于管理。这为您提供了可管理且易于理解的结果集。使用 linq 应用剩余的区别。
您可以利用两者的优点:
减少总记录 可以在服务器上;得到尽可能多的 疯狂加入 服务器。数据库在这方面很好 东西。 Linq(对象等)没有那么强大,但擅长表达复杂的标准;因此,将其用于各种可能的区别,这些区别会增加代码的复杂性,但数据库在处理方面并不会更好。 linq 在简化的标准化结果集上运行,可以表达复杂性而不会造成太多性能损失。如何决定在 db 中处理哪些条件以及使用 linq 处理哪些条件?用你的判断。如果您可以有效地处理复杂的数据库查询,则可以处理。部分艺术,部分科学。
【讨论】:
你的意思是让数据库做它擅长的事情?我认为完成的 linq KristoferA 令人印象深刻。另一方面,我更乐意使用一些事务 SQL 来控制数据库的性能。请注意,数据库的抽象层可以是一组类。 linq 方法似乎是一种通用编程,但实际上您需要 linq 框架以最佳方式管理查询。因此,虽然在技术上令人印象深刻,但如果没有别的,它似乎有点不透明,而且我的 prod 环境无论如何都将这些东西放在存储过程中。 @polyglot 是的,这里有很多因素,如果我们有更多细节,我们所有人都会给出更有针对性的建议。对于一个复杂的搜索引擎,我根据我的经验做出了一个很好的猜测,那就是性能和可维护性。在 KristoferA 的示例中使用动力学可能会带来超过其灵活性的性能损失。 Linq to generic enumerables 以可接受的成本提供简单性,只要已经完成了一些繁重的工作。并且由于逻辑非常复杂,我不相信 Linq-to-sql 可以有效地设置数据库工作。还没有。【参考方案9】:您可能需要考虑 LINQ 或像这样的 O/R 映射器:http://www.llblgen.com/
【讨论】:
【参考方案10】:如果使用 C# 和 .NET 3.5,再加上 MS SQL Server,那么 LINQ to SQL 绝对是要走的路。如果您使用的不是该组合,我建议您使用 ORM 路由,例如 nHibernate 或 Subsonic。
【讨论】:
【参考方案11】:在http://www.blackbeltcoder.com/Articles/strings/a-sql-querybuilder-class 的 QueryBuilder 类中有一种实验性尝试。可能值得一看。
【讨论】:
【参考方案12】:查看http://sqlom.sourceforge.net。我认为它完全符合您的要求。
【讨论】:
以上是关于在 C#/.NET3.5 中构造动态 sql 查询的最佳方式?的主要内容,如果未能解决你的问题,请参考以下文章