在C#/ .NET3.5中构建动态SQL查询的最佳方法?

我正在研究的一个项目涉及重构一个C#Com对象,它作为一些Sql 2005数据库的数据库访问层。

现有代码的作者使用字符串和许多if语句手动构建了所有sql查询,以构造相当复杂的sql语句(~10个连接,> 10个子选择,~15-25 where条件和GroupBy)。 基表始终是相同的,但连接,条件和分组的结构取决于传递给我的类/方法的一组参数。

构建像这样的SQL查询确实有效,但它显然不是一个非常优雅的解决方案(而且很难阅读/理解和维护)…我可以自己写一个简单的“querybuilder”,但我很确定我不是第一个遇到这种问题的人,因此我的问题是:

  • 你如何构建数据库查询?
  • C#是否提供了一种动态构建查询的简便方法?

我使用C#和Linq做类似的事情来获取在用户输入上过滤的日志条目(请参阅条件Linq查询 ):

IQueryable 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()才执行查询。

除非执行时间非常重要,否则我会考虑重构业务逻辑(经常)往往会找到数据层并进入数十亿存储过程。 在维护性,可编辑性和可附加性方面,我总是尝试(作为C#程序员)将代码提升到业务层。

试图找出别人的8000行SQL脚本不是我最喜欢的任务。

🙂

// w ^

LINQ是要走的路。

这就是我这样做的方式:

 public IQueryable GetClients(Expression> 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等构建的动态查询。此Expression将在运行时获取Invoked并为您提供所需的内容。

以下是如何调用它的示例:

 public IQueryable GetClientsWithWebAccountId(int webAccountId) { var criteria = PredicateBuilder.True(); criteria = criteria.And(c => c.ClientWebAccount.WebAccountId.Equals(webAccountId)); return GetClients(criteria); } 

如果您可以实现作为参数化的条带化过程并在数据库中对其进行优化而不是在运行时通过LINQ或ORM动态生成SQL,则值得考虑。 通常这会表现得更好。 我知道它有点老式,但有时它是最有效的方法。

我理解Linq的潜力,但我还没有看到任何人尝试对Lin所提出的复杂性进行Linq查询

相当复杂的sql语句(~10个连接,> 10个子选择,~15-25 where条件和GroupBy)

有没有人有大型Linq查询的例子,以及有关其可管理性的任何评论?

Linq to SQL与System.Linq.Dynamic一起带来了一些很好的可能性。

我在这里发布了几个示例代码片段: 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

我来这里已经很晚了,并没有机会进行upvote,但是我有一个很好的解决方案,我没有考虑过:程序/function与linq-to-object的组合。 或者我认为to-xml或to-datatable。

在这种情况下我一直都是这样,有一个巨大的动态构建的查询,这是一个令人印象深刻的成就,但其复杂性导致了维护噩梦。 我有这么多绿色评论来帮助那些不得不过来并且理解它的可怜的闷棍。 我是经典的asp,所以我没有其他选择。

我之所以做的是function/程序和linq的结合 。 通常, 总复杂性低于尝试在一个地方进行复杂化的复杂性。 将您的一些标准传递给UDF,这将变得更易于管理。 这为您提供了易于管理且易于理解的结果集。 使用linq应用您剩余的区别。

您可以利用两者的优势:

  • 在服务器上尽可能减少总记录数; 在服务器上获得尽可能多的疯狂联接。 数据库很擅长这个东西。
  • Linq(对象等)没有那么强大,但却很擅长表达复杂的标准; 因此,将它用于各种可能的区别,这会增加代码的复杂性,但数据库在处理方面不会更好。 在缩小的归一化结果集上运行,linq可以表达复杂性,而不会造成太多性能损失。

如何确定在db中处理哪个条件以及使用linq处理哪个条件? 用你的判断。 如果您可以有效地处理复杂的数据库查询,则可以处理此问题。 部分艺术,部分科学。

您可能需要考虑像这样的LINQ或O / R Mapper: http : //www.llblgen.com/

如果使用C#和.NET 3.5,添加MS SQL Server,那么LINQ to SQL绝对是可行的方法。 如果您使用的不是该组合,我建议使用ORM路由,例如nHibernate或Subsonic 。

在http://www.blackbeltcoder.com/Articles/strings/a-sql-querybuilder-class上的QueryBuilder类中进行了一次实验性尝试。 也许值得一瞧。

查看http://sqlom.sourceforge.net 。 我认为它完全符合您的要求。