为什么 EF 4.1 不支持复杂查询以及 linq-to-sql? [英] Why does EF 4.1 not support complex queries as well as linq-to-sql?

查看:26
本文介绍了为什么 EF 4.1 不支持复杂查询以及 linq-to-sql?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将我们的内部 Web 应用程序从 Linq-To-Sql 转换为现有数据库中的 EF CodeFirst.我最近越来越对 Linq-To-Sql 的限制感到恼火,并且在更新一个非常复杂的数据库表后不得不更新 edmx 终于让我感到沮丧到切换到 EF.

I am in the process of converting our internal web application from Linq-To-Sql to EF CodeFirst from an existing database. I have been getting annoyed with Linq-To-Sql's limitations more and more lately, and having to update the edmx after updating a very intertwined database table finally frustrated me enough to switch to EF.

但是,我遇到了几种情况,其中将 linq 与 Linq-To-Sql 一起使用比最新的实体框架更强大,我想知道是否有人知道其中的原因?其中大部分似乎与转换有关.例如,以下查询在 L2S 中有效,但在 EF 中无效:

However, I am encountering several situations where using linq with Linq-To-Sql is more powerful than the latest Entity Framework, and I am wondering if anyone knows the reasoning for it? Most of this seems to deal with transformations. For example, the following query works in L2S but not in EF:

        var client = (from c in _context.Clients
                      where c.id == id
                      select ClientViewModel.ConvertFromEntity(c)).First();

在 L2S 中,这会正确地从数据库中检索客户端并将其转换为 ClientViewModel 类型,但在 EF 中,此异常表示 Linq to Entities 无法识别该方法(这是有道理的,因为我写了.

In L2S, this correctly retrieves a client from the database and converts it into a ClientViewModel type, but in EF this exceptions saying that Linq to Entities does not recognize the method (which makes sense as I wrote it.

为了让它在 EF 中工作,我必须将 select 移动到 First() 调用之后.

In order to get this working in EF I have to move the select to after the First() call.

另一个例子是我检索客户列表的查询.在我的查询中,我将其转换为匿名结构以转换为 JSON:

Another example is my query to retrieve a list of clients. In my query I transform it into an anonymous structure to be converted into JSON:

        var clients = (from c in _context.Clients
                       orderby c.name ascending
                       select new
                       {
                           id = c.id,
                           name = c.name,
                           versionString = Utils.GetVersionString(c.ProdVersion),
                           versionName = c.ProdVersion.name,
                           date = c.prod_deploy_date.ToString()
                       })
                       .ToList();

不仅我的 Utils.GetVersionString() 方法导致 EF 中不受支持的方法异常,c.prod_deploy_date.ToString() 也会导致异常,而且很简单日期时间.像以前一样,为了修复它,我必须在 ToList() 之后进行选择转换.

Not only does my Utils.GetVersionString() method cause an unsupported method exception in EF, the c.prod_deploy_date.ToString() causes one too and it's a simple DateTime. Like previously, in order to fix it I had to do my select transformation after ToList().

<小时>编辑:我刚刚遇到的另一个案例是 EF 无法处理比较实体的 where 子句,因为 L2S 没有问题.例如查询


Edit: Another case I just came across is that EF cannot handle where clauses that compare entities where as L2S has no issues for with it. For example the query

context.TfsWorkItemTags.Where(x => x.TfsWorkItem == TfsWorkItemEntity).ToList()

抛出异常,而我必须这样做

throws an exception and instead I have to do

context.TfsWorkItemTags.Where(x => x.TfsWorkItem.id == tfsWorkItemEntity.id).ToList() 

<小时>编辑 2:我想添加我发现的另一个问题.显然你不能在 EF Linq 查询中使用数组,这可能比任何事情都让我烦恼.例如,现在我将表示版本的实体转换为 int[4] 并尝试对其进行查询.在 Linq-to-Sql 中,我使用了以下查询:


Edit 2: I wanted to add another issue that I found. Apparently you can't use arrays in EF Linq queries, and this probably annoys me more than anything. So for example, right now I convert an entity that denotes a version into an int[4] and try to query on it. In Linq-to-Sql I used the following query:

return context.ReleaseVersions.Where(x => x.major_version == ver[0] && x.minor_version == ver[1]
                                          && x.build_version == ver[2] && x.revision_version == ver[3])
                              .Count() > 0;

此操作失败,但出现以下异常:

This fails with the following exception:

The LINQ expression node type 'ArrayIndex' is not supported in LINQ to Entities.

<小时>

编辑 3:我发现了另一个 EF 糟糕的 Linq 实现实例.以下是在 L2S 中有效但在 EF 4.1 中无效的查询:


Edit 3: I found another instance of EF's bad Linq implementation. The following is a query that works in L2S but doesn't in EF 4.1:

        DateTime curDate = DateTime.Now.Date;
        var reqs = _context.TestRequests.Where(x => DateTime.Now > (curDate + x.scheduled_time.Value)).ToList();

这将抛出一个 ArgumentException 消息 DbArithmeticExpression 参数必须具有数字公共类型.

This throws an ArgumentException with the message DbArithmeticExpression arguments must have a numeric common type.

<小时>为什么看起来他们在 EF 中比在 L2S 中降低了 Linq 查询的能力?


Why does it seem like they downgraded the ability for Linq queries in EF than in L2S?

推荐答案

编辑 (9/2/2012): 更新以反映 .NET 4.5 并添加了更多缺失的功能

Edit (9/2/2012): Updated to reflect .NET 4.5 and added few more missing features

这不是答案 - 不可能是因为唯一可以回答您问题的合格人员可能是 ADO.NET 团队的产品经理.

This is not the answer - it cannot be because the only qualified person who can answer your question is probably a product manager from ADO.NET team.

如果您检查旧数据集的功能集,然后检查 linq-to-sql 和 EF,您会发现在较新的 API 中删除了关键功能,因为较新的 API 是在更短的时间内开发出来的,并且付出了巨大的努力来提供新的奇特功能.

If you check feature set of old datasets then linq-to-sql and then EF you will find that critical features are removed in newer APIs because newer APIs are developed in much shorter times with big effort to deliver new fancy features.

仅列出数据集中可用但在以后的 API 中不可用的一些关键功能:

Just list of some critical features available in DataSets but not available in later APIs:

  • 批处理
  • 唯一键

Linq-to-Sql 中可用但 EF 不支持的功能(可能列表不完全正确,我很久没有使用 L2S):

Features available in Linq-to-Sql but not supported in EF (perhaps the list is not fully correct, I haven't used L2S for a long time):

  • 记录数据库活动
  • 延迟加载的属性
  • 左外连接 (DefaultIfEmpty) 自第一个版本(EF 自 EFv4 起就有)
  • 全局预加载定义
  • AssociateWith - 例如预先加载数据的条件
  • 从第一个版本开始编写代码
  • IMultipleResults 支持返回多个结果集的存储过程(EF 在 .NET 4.5 中有它,但没有设计器支持此功能)
  • 支持表值函数(EF 在 .NET 4.5 中有此功能)
  • 还有其他一些
  • Logging database activity
  • Lazy loaded properties
  • Left outer join (DefaultIfEmpty) since the first version (EF has it since EFv4)
  • Global eager loading definitions
  • AssociateWith - for example conditions for eager loaded data
  • Code first since the first version
  • IMultipleResults supporting stored procedures returning multiple result sets (EF has it in .NET 4.5 but there is no designer support for this feature)
  • Support for table valued functions (EF has this in .NET 4.5)
  • And some others

现在我们可以列出 EF ObjectContext API (EFv4) 中可用但 DbContext API (EFv4.1) 中缺少的功能:

Now we can list features available in EF ObjectContext API (EFv4) and missing in DbContext API (EFv4.1):

  • 映射存储过程
  • 条件映射
  • 映射数据库函数
  • 定义查询、查询视图、模型定义的函数
  • ESQL 不可用,除非您将 DbContext 转换回 ObjectContext
  • 除非您将 DbContext 转换回 ObjectContext
  • ,否则无法操作独立关系的状态
  • 使用 MergeOption.OverwriteChangesMergeOption.PreserveChanges 是不可能的,除非您将 DbContext 转换回 ObjectContext
  • 还有其他一些
  • Mapping stored procedures
  • Conditional mapping
  • Mapping database functions
  • Defining queries, QueryViews, Model defined functions
  • ESQL is not available unless you convert DbContext back to ObjectContext
  • Manipulating state of independent relationships is not possible unless you convert DbContext back to ObjectContext
  • Using MergeOption.OverwriteChanges and MergeOption.PreserveChanges is not possible unless you convert DbContext back to ObjectContext
  • And some others

我个人对此的感受只是巨大的悲伤.由于 ADO.NET 团队显然没有足够的资源来重新实现它们,因此缺少核心功能并且删除了以前 API 中存在的功能 - 这使得在许多情况下几乎不可能迁移路径.整个情况更糟,因为没有直接列出缺失的功能或迁移障碍(恐怕连 ADO.NET 团队都不知道,直到有人报告它们).

My personal feeling about this is only big sadness. Core features are missing and features existing in previous APIs are removed because ADO.NET team obviously doesn't have enough resources to reimplement them - this makes migration path in many cases almost impossible. The whole situation is even worse because missing features or migration obstacles are not directly listed (I'm afraid even ADO.NET team doesn't know about them until somebody reports them).

因此,我认为 DbContext API 的整个想法是管理失败.目前 ADO.NET 团队必须维护两个 API - DbContext 还没有成熟来取代 ObjectContext 并且它实际上不能,因为它只是一个包装器,因为 DbContextcode>ObjectContext 不能死.可用于 EF 开发的资源很可能减少了一半.

Because of that I think that whole idea of DbContext API was management failure. At the moment ADO.NET team must maintain two APIs - DbContext is not mature to replace ObjectContext and it actually can't because it is just a wrapper and because of that ObjectContext cannot die. Resources available for EF development was most probably halved.

还有更多相关的问题.一旦我们离开 ADO.NET 团队,从 MS 产品套件的角度来看问题,我们会看到很多差异,我有时甚至怀疑是否有任何全局策略.

There are more problems related. Once we leave ADO.NET team and look on the problem from the perspective of MS product suite we will see so many discrepancies that I sometimes even wonder if there is any global strategy.

简单地接受这样一个事实,即 EF 的提供程序以不同的方式工作,并且在 Linq-to-sql 中工作的查询不必与 EF 一起使用.

Simply live with the fact that EF's provider works in different way and queries which worked in Linq-to-sql don't have to work with EF.

这篇关于为什么 EF 4.1 不支持复杂查询以及 linq-to-sql?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆