将LINQ表达式转换为没有DB Context的SQL Text

时间:2013-03-05 16:02:31

标签: c# .net sql linq expression-trees

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

我想将LINQ表达式转换为WHEREORDER BY子句的等效SQL字符串,而不使用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文本”工具,类似于在我上面的存储库中工作的expression tree to SQL example。它允许我编写这样的代码:

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之类的工具。

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

  • 我在IRepository.Find方法中输入的谓词具有智能感知和基本编译时检查。
  • 我建议的IStore接口可以实现数据库访问或Web服务访问。为了澄清,如果我可以将LINQ“WHERE / ORDER BY”谓词转换为SQL“WHERE / ORDER BY”子句,那么......
    • Dapper可以直接使用SQL字符串。
    • 与LINQ表达式不同,SQL字符串可以发送到WCF服务以用于直接数据库访问(它本身可能不使用Dapper)。
    • 可以将带有custom code的SQL字符串反序列化为WCF服务的LINQ语句。 Eric Lippert comments on this
  • UI可以使用IQueryable机制动态生成谓词以提供存储库

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

3 个答案:

答案 0 :(得分:3)

正确地执行此操作非常复杂,特别是如果现在,您似乎对表达式树(IQueryable用于表示查询)知之甚少。

但是如果你真的想要开始(或者只是想知道它会有多少工作),那就看看Matt Warren的17部分系列Building an IQueryable provider

答案 1 :(得分:2)

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

如果所有这些都不是障碍,那么这个练习实际上可以是非常愉快和有益的,至少在第一个月左右。我注意到这些提供商中的一个常见问题是,一开始就缺乏灵活性和可疑的设计选择导致后期困难和黑客修复等。事先规划尽可能多,清楚地了解整个过程,不同阶段,组件正确识别层并且担心会使开发它变得容易得多。我在一个提供程序中看到的最大错误是 - 未能将输出查询分解为其部分 - select,from,where和order by。每个部分应该由它自己的对象表示,然后在最后组合在一起。我在端到端教程中解释了这种方法,该教程介绍了如何在下面链接的系列中编写提供程序。这里有一个示例项目,包括一个simpleiefied / tutorial变体,以及从头开始为项目制作的完整版本。找到时间来撰写它本身就是一个挑战。

答案 2 :(得分:1)

这是我很久以前简要介绍的内容。您可能需要查看http://iqtoolkit.codeplex.com/和/或http://expressiontree.codeplex.com/的想法。正如其他人所提到的,如果您不将范围限制为您真正需要的最小功能集,那么Linq查询提供程序的构建绝非易事。

如果您的目标与&#34;规范&#34;或者&#34;查询对象&#34;根据DDD的存储库概念,这可能不是最好的方向。与技术相关的抽象相似的CRUD,可能更有效地关注可以表达域行为的方式,而对技术相关抽象的直接依赖性最小。正如埃里克·埃文斯最近所讨论的那样,他对DDD最初描述中对技术构建模块(如存储库)的关注感到遗憾。