5

由于EF4无法将某些表达式转换为SQL,因此我们在相当大的系统中使用EF4并偶尔遇到问题。目前,我们或者需要做一些奇特的步法(DB/Code),或者只是接受性能命中,并允许查询在内存中执行。扩展EF4 SQL生成

不用说,这些都不是理想的,我们有时不得不使用的黑客降低可读性/可维护性。

我们理想的想法是扩展EF4 SQL提供程序的SQL生成功能。很明显,有些东西就像.Net方法调用一样必须是客户端,但是一些功能比如日期比较(例如[Linq到Entities的星期几组)应该可用。

我已经谷歌搜索,但也许我使用错误的术语,因为我所得到的是有关EF4 SQL生成的新功能的信息。

对于这样一个灵活和可扩展的框架,如果这是不可能的,我会感到惊讶。在我的脑海中,我想象着从[SQL 2008]提供者继承,并将其扩展为处理其转换为SQL的表达式树中的其他表达式/类似表达式。

任何帮助/指针赞赏。

我们使用VS2010 Ultimate,.Net 4(非客户端配置文件)和EF4。该应用程序在ASP.Net,并在64位环境中运行,以防有所作为。

更新:回应一些澄清要求;

我们使用的是代码优先的方法,并有一个控制台应用程序来创建数据库并填充一些引用表。

我宁愿远离存储过程,除非它们也可以以类似的方式生成 - 目前,根据需要生成数据库的新版本,并且单独的过程会迁移/同步数据。 一切我们目前正在处理数据库使用实体。我承认我不能给出一个很好的理由,但是在这种情况下运行SQL脚本来生成存储过程感觉不对 - 但是如果我错了,请纠正我的错误。

关于具体情况,恐怕我不能在没有经过冗长的繁文exercise节练习的情况下从我们的代码中提供一个代码 - link mentioned above是我们尝试的那类事情的一个很好的例子完成。在这个例子中,实现一种机制,允许日期计算:

DateTime firstDay = GetFirstDayOfFirstWeekOfYear(); 
var userTimes = from t in context.TrackedTimes 
       group t by new {t.User.UserName, WeekNumber = (t.TargetDate - firstDay).Days/7} into ut 
       select new 
       { 
        UserName = ut.Key.UserName, 
        WeekNumber = ut.Key.WeekNumber, 
        Minutes = ut.Sum(t => t.Minutes) 
       }; 

我可以看到一个办法,这可以使用SQL孤单但不知道如何使用LINQ到实体(服务器端)做它来完成。

+0

很难回答这样一个抽象的问题。你正准备支持什么呢?有很多种方法来做这些事情(EdmFunctions,商店查询,执行文字SQL等)。 – 2010-06-08 14:15:08

+0

确实 - 我已经扩展了这个问题来包含一个例子。我希望这更清楚? – Basic 2010-06-08 16:51:25

回答

9

我会先寻找建议在EntityFunctions(通用)或SqlFunctions(仅适用于SQL Server)的,其提供在正常的LINQ to Entities查询中有许多内置的数据库功能。如果这还不够,可以使用EdmFunctionAttribute来映射内置数据库函数或用户定义的存储过程。第三个选项是尝试使其作为实体SQL查询来工作。

您建议的最后一个解决方案 - 编写一个EF提供者 - 相当重量级。编写一个包装现有SQL提供程序的EF提供程序是可能的,但您至少必须将某些表达式树更改为Entity SQL。非常简单的EF提供者包装已在MSDN Code上发布。不过,我认为这是最后的手段。

+0

感谢您提供非常有用的链接。我需要做一些阅读并回复你 – Basic 2010-06-08 17:14:41

+0

非常棒,谢谢 - 我们有很多选择,我们可能会混合搭配 – Basic 2010-06-13 22:37:10

1

从您的基于.NET的LINQ查询到SQL的转换由LINQ To Entities Provider处理。我不相信这个非常复杂的核心翻译/编译过程是可扩展的。你将不得不从头开始编写自己的提供程序。

我还没有遇到任何可以用SQL表示的查询,这些查询不能用LINQ表示。如果你确实有一个很难写作LINQ查询的查询,你有没有考虑过使用存储过程呢?如果你能提供一些不会转换的查询的例子,这将有所帮助。

UPDATE:

另一种选择是创建使用定制表达式以表格先进的扩展方法。这里是模拟载有()函数来执行“其中”类型的查询一个很好的例子:

'Contains()' workaround using Linq to Entities?

+0

感谢您的回答。 Contains()的链接非常有趣,但并不完全符合我们的要求。我们已经有适当的扩展方法,将Expression和Expression方法添加到Expressions.Expression(Of Func(Of T,Boolean))中,以便合适地合并表达式 - 这对于组合来自不同层的多个查询非常方便应用程序(例如添加安全限制)但是,因为我无法看到使用LINQ修改查询的方式(例如,日期减法/日期分割),所以我不明白我该如何应用这种技术? – Basic 2010-06-08 17:09:01

+0

回应你的答案的第一部分,这看起来正是我想要做的,我开始怀疑它不可扩展,因为我没有在其他地方找到任何信息,我当然不能写 – Basic 2010-06-08 17:13:54

+0

CAST(DateTimeOffset as DateTime)<<<<<<祝你好运,在Linq-To-Entities中做到了这一点,它不可能完成,它非常简单, DateTimeOffset的DateTime部分在linq-to-entities中是不可能的,所以你可以甚至没有按照当地的日期和时间过滤DateTimeOffset列,这违背了它存在的全部目的。 – Triynko 2016-12-14 18:33:54