17

LINQ to SQL 或 LINQ to Entities 已经能够将 LINQ 转换为 SQL 文本字符串。但我希望我的应用程序在不使用 db 上下文的情况下进行转换——这反过来意味着一个活动的数据库连接——这两个提供者都需要。

我想将 LINQ 表达式转换为等效的 SQL 字符串 for WHEREandORDER BY子句,而不依赖于 DB 上下文,以使以下存储库接口工作:

public interface IStore<T> where T : class 
{
     void Add(T item);
     void Remove(T item);
     void Update(T item);
     T FindByID(Guid id);

     //sure could use a LINQ to SQL converter!
     IEnumerable<T> Find(Expression<Func<T, bool>> predicate);
     IEnumerable<T> FindAll();
}

问题

它主要是我感兴趣的表达式树遍历和转换。有人知道我可以合并以在这种自定义上下文中使用的现有库(nuget?)吗?

因为它是我已经建立了我自己的工作“LINQ 转换为 SQL 文本”工具,类似于在我上面的存储库中工作的这个表达式树到 SQL 示例。它允许我编写如下代码:

IRepository<Person> repo = new PersonRepository();
var maxWeight = 170;
var results = repo.Find(x => (x.Age > 40 || x.Age < 20) && x.Weight < maxWeight);

但是我的代码和该示例是原始的(并且该示例本身依赖于 LINQ to SQL db 上下文)。例如,两者都不处理“LIKE”语句的生成。

我不期望或不需要处理所有可能的 LINQ 查询的生成器工具。例如,我不担心处理和生成连接或包含。事实上,再过 20 个小时,我自己的自定义代码可能会涵盖我关心的所有情况(主要是“WHERE”和“ORDER BY”语句)。

但同时我觉得我不应该编写自己的自定义代码来做到这一点。如果我坚持自己编写,那么如果有人能指出我可以反映和模仿的特定类(NHibernate、EF 等),我仍然会感兴趣。我问的是要查看的特定类,如果你知道的话,因为我不想花几个小时筛选一个大型工具的代码,只是为了找到我需要的部分。

这并不重要,但如果有人想知道我为什么不简单地使用 LINQ to SQL 或 LINQ to Entities ......对于我的特定应用程序,我只是更喜欢使用诸如Dapper之类的工具。

用例 无论是我自己完成了工具的构建,还是找到了第 3 方库,以下是“LINQ to SQL 文本字符串”有用的原因:

  • 我在方法中键入的谓词IRepository.Find具有智能感知和基本的编译时检查。
  • 我提出的 IStore 接口可以实现用于 DB 访问或 Web 服务访问。澄清一下,如果我可以将 LINQ“WHERE/ORDER BY”谓词转换为 SQL“WHERE/ORDER BY”子句,那么......
  • UI 可以使用 IQueryable 机制动态生成谓词以提供给存储库

简而言之,这样的工具有助于根据 DDD 实现存储库的“规范”或“查询对象”概念,并且不会依赖 EF 或 LINQ to SQL。

4

3 回答 3

4

正确地执行此操作确实非常复杂,尤其是如果现在,您似乎对表达式树(IQueryable用于表示查询的内容)了解不多。

但是,如果您真的想开始(或者只是想知道需要做多少工作),请查看 Matt Warren 的 17 部分系列Building an IQueryable provider

于 2013-03-05T18:59:00.697 回答
2

我可以确认这是一项相当大的工作量,只适合最有经验的 .NET 开发人员。精通C#,具有多种语言的经验,包括T-SQL是必须的。必须非常精通 C#(或 VB.NET)和 T-SQL,因为他们必须将使用前者的翻译器编写到后者中。此外,这属于元编程领域,它被认为是计算机科学的一个相当先进的分支。涉及很多抽象思维。层层叠叠的抽象概念。

如果所有这些都不是障碍,那么这个练习实际上会非常愉快和有益,至少在第一个月左右。我注意到这些提供商的一个常见问题是,一开始的不灵活和有问题的设计选择导致后来的困难和hacky修复等。尽可能提前计划,清楚地了解整个过程,不同阶段,组件正确识别层并且担心会使开发它变得容易得多。我在一个提供者中看到的最大错误是——未能将输出查询分解为多个部分——选择、来自、位置和排序依据。每个部分都应始终由其自己的对象表示,然后在最后组合在一起。我在关于如何在下面链接的系列中编写提供程序的端到端教程中解释了这种方法。包含一个示例项目,带有简化/教程变体和从头开始为项目制作的完整版本。找时间写这篇文章本身就是一个挑战。

于 2015-07-03T03:40:33.420 回答
1

这是我不久前简要研究过的事情。您可能想查看http://iqtoolkit.codeplex.com/和/或http://expressiontree.codeplex.com/的想法。正如其他人所提到的,如果您不将范围限制在您真正需要的最小功能集,则构建 Linq 查询提供程序绝非易事。

如果您的目标与根据 DDD 的存储库的“规范”或“查询对象”概念相关,那么这可能不是最好的方向。与 CRUD 之类的技术相关抽象不同,关注领域行为可以表达的方式可能更有效率,而对技术相关抽象的直接依赖最少。正如 Eric Evans 最近所讨论的,他对在最初描述 DDD 时对技术构建块(例如存储库)的关注感到遗憾。

于 2013-07-12T03:14:23.120 回答