8

我目前正在进行的一个项目涉及重构一个 C# Com 对象,该对象用作某些 Sql 2005 数据库的数据库访问层。

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

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

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

12 回答 12

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

于 2008-09-15T15:05:20.477 回答
2

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

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

:)

//W

于 2008-09-15T20:18:27.790 回答
1

LINQ是要走的路。

于 2008-09-15T13:46:43.647 回答
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 等构建的动态查询。此表达式将在运行时被调用并为您提供所需的内容。

这是如何调用它的示例:

public IQueryable<ClientEntity> GetClientsWithWebAccountId(int webAccountId)
    {
        var criteria = PredicateBuilder.True<ClientModel>();
        criteria = criteria.And(c => c.ClientWebAccount.WebAccountId.Equals(webAccountId));
        return GetClients(criteria);
    }
于 2008-09-15T15:13:27.510 回答
1

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

于 2008-09-15T15:24:31.273 回答
1

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

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

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

于 2008-09-15T23:06:17.903 回答
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

于 2008-09-16T06:32:03.230 回答
1

我来晚了,没有机会投票,但是有一个我没有考虑过的很好的解决方案:过程/函数与 linq-to-object 的组合。或者我想是 to-xml 或 to-datatable。

在这种情况下,我一直处于这种状态,使用大量动态构建的查询,这是一项令人印象深刻的成就,但其复杂性却成为维护的噩梦。我有这么多绿色评论来帮助后来不得不出现并理解它的可怜的树液。我使用的是经典的 asp,所以我几乎没有其他选择。

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

您可以利用两者的优点:

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

如何决定在数据库中处理哪些标准以及使用 linq 处理哪些标准?用你的判断。如果您可以有效地处理复杂的数据库查询,则可以处理。部分艺术,部分科学。

于 2009-12-23T19:12:12.177 回答
0

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

于 2008-09-15T13:47:02.367 回答
0

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

于 2008-09-15T15:38:48.947 回答
0

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

于 2011-01-28T01:45:34.677 回答
0

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

于 2011-03-09T11:55:03.107 回答