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

时间:2008-09-15 13:44:19

标签: c# sql sql-server linq .net-3.5

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

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

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

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

12 个答案:

答案 0 :(得分:9)

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

答案 1 :(得分:2)

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

尝试解决别人的问题8000行SQL脚本不是我最喜欢的任务。

:)

// w ^

答案 2 :(得分:1)

LINQ是要走的路。

答案 3 :(得分:1)

这就是我的方式:

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等构建的动态查询。此表达式将在运行时获得 Invoked 并给你你需要的东西。

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

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

答案 4 :(得分:1)

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

答案 5 :(得分:1)

我理解Linq的潜力,但我还没有看到有人试图对Lin的建议复杂性进行Linq查询

  

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

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

答案 6 :(得分:1)

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

答案 7 :(得分:1)

我迟到了,没有机会进行upvote,但有一个很好的解决方案,我没有考虑过:程序/功能与linq-to-object的组合。或者我想是to-xml或to-datatable。

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

我所做的是功能/程序和linq 的组合。通常,总复杂度小于尝试在一个地方执行它的复杂性。将您的一些标准传递给UDF,这会变得更易于管理。这为您提供了易于管理且易于理解的结果集。使用linq。

应用您剩余的区别

您可以利用两者的优势:

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

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

答案 8 :(得分:0)

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

答案 9 :(得分:0)

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

答案 10 :(得分:0)

http://www.blackbeltcoder.com/Articles/strings/a-sql-querybuilder-class的QueryBuilder类中进行了一次实验性尝试。可能值得一看。

答案 11 :(得分:0)

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