c# - EF4 : LINQ 2 Entities query works in C# but not in VB

标签 c# vb.net entity-framework-4

[已编辑:我在下面留下了原始问题,并提供了更多上下文和代码来重现该问题。下面的简短版本包含问题的本质]

简短版本:下面的查询抛出 System.NotSupportedException:“无法将类型‘System.Linq.IOrderedQueryable1’转换为类型‘System.Linq.IQueryable1’。LINQ to Entities仅支持转换实体数据模型原始类型。”该异常仅在 VB.Net 版本中出现。翻译成 C# 时,不会引发异常。

   Dim doesThisCrash = From outerOrder In orders
        Where outerOrder.ProductId =
        (From p In products Join o In orders On p.Id Equals o.ProductId
         Order By p.Id
         Select p.Id).FirstOrDefault()
        Select outerOrder
    doesThisCrash.ToList()

因此,为了让它崩溃,我们似乎需要一个子查询,其中原始 ObjectSet(订单)与另一个 ObjectSet(产品)连接并排序。仅使用订单或产品集时,不会发生崩溃。当省略 Order By 时,也没有崩溃。

我倾向于认为这是一个 (VB.Net) 编译器错误,除非我在这里忽略了一些明显的东西......

现在我的问题仍然存在:

  • 为什么看似完全相同的查询在 C# 中有效,但在 VB 中却无效?
  • 可以使这个查询在 VB.Net 中工作吗?

[/编辑]

可选的,更长的版本(原始问题):

我的域看起来非常不同,但我将问题转化为一个更简单的版本,具有以下实体(注意:我实际上使用 .edmx 设计器定义了这些,所以这是一个简化版本):

    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public DateTime DateCreated { get; set; }
    }

    public class Order
    {
        public int Id { get; set; }
        public int CustomerId { get; set; }
        public int ProductId { get; set; }
        public DateTime OrderDate { get; set; }
    }

    public class Customer
    {
        public int Id { get; set; }
    }

我正在尝试在 VB.Net 中制定一个 linq-to-entities 查询,它在结构上应该看起来像这样:

    Dim db = New SampleEntities()
    Dim orders As IQueryable(Of Order) = db.Orders
    Dim products As IQueryable(Of Product) = db.Products
    Dim currentDate = DateTime.Now

    Dim qLinq = From outerOrder In orders
                Where outerOrder.OrderDate = currentDate AndAlso
                outerOrder.ProductId =
                    (From p In products Join o In orders On p.Id Equals o.ProductId
                     Where o.OrderDate = outerOrder.OrderDate AndAlso
                            outerOrder.CustomerId = o.CustomerId
                     Order By p.DateCreated
                     Select p.Id).FirstOrDefault()
                Select outerOrder

这会引发 System.NotSupportedException:

“无法将类型‘System.Linq.IOrderedQueryable1’转换为类型‘System.Linq.IQueryable1’。LINQ to Entities 仅支持转换实体数据模型基元类型。”

当省略“Order By”部分时,不会引发异常。

我真的不明白为什么不支持这个查询的原因...所以我决定在 C# 中尝试同样的事情:

var qLinq = from oOut in orders
            where oOut.OrderDate == currentDate
                  && oOut.ProductId == 
                          (from p in products join o in orders on p.Id equals o.ProductId
                           where oOut.OrderDate == o.OrderDate 
                           && oOut.CustomerId == o.CustomerId
                           orderby p.DateCreated
                           select p.Id).FirstOrDefault()
                    select oOut;

令我惊讶的是,这有效!然后我将 C# 查询转换为扩展方法语法,然后返回到 VB,但得到了相同的结果(C# 版本有效,VB.Net 版本引发了相同的异常)。

所以我想我的问题是双重的:

  • 为什么看似完全相同的查询在 C# 中有效,但在 VB 中却无效?
  • 可以使这个查询在 VB.Net 中工作吗?

作为引用,以下是扩展方法语法中的查询:

C#版本:

        var q = orders.Where(outerOrder => 
            outerOrder.OrderDate == currentDate &&
            outerOrder.ProductId == 
            (products
                .Join(orders, 
                    f => f.Id, 
                    o => o.ProductId,
                    (f, o) => new { f, o })
                .Where(t => t.o.OrderDate == outerOrder.OrderDate 
                           && outerOrder.CustomerId == t.o.CustomerId)
                .OrderByDescending(t => t.f.DateCreated)
                .Select(t => t.f.Id))
                .FirstOrDefault());

VB.Net 版本:

    Dim q = orders.Where(Function(outerOrder) outerOrder.OrderDate = currentDate AndAlso
                             outerOrder.ProductId = (products.Join(orders,
                               Function(p) p.Id,
                               Function(o) o.ProductId,
                               Function(p, o) New With {.p = p, .o = o}).
                           Where(Function(x) x.o.OrderDate = outerOrder.OrderDate AndAlso
                                     outerOrder.CustomerId = x.o.CustomerId).
                           OrderByDescending(Function(x) x.p.DateCreated).
                           Select(Function(x) x.p.Id).
                           FirstOrDefault()))

最佳答案

我认为以下是有效的,尽管 SQL 很丑陋:

Dim qLinq = From outerOrder In orders
                Where outerOrder.OrderDate = currentDate AndAlso
                outerOrder.ProductId =
                    (From x In (From p In products
                                 Join o In orders On p.Id Equals o.ProductId
                                 Where o.OrderDate = outerOrder.OrderDate AndAlso
                                        outerOrder.CustomerId = o.CustomerId
                                 Select p.Id)
                    Order By x).FirstOrDefault()
                Select outerOrder

关于c# - EF4 : LINQ 2 Entities query works in C# but not in VB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4416887/

相关文章:

C# - 将匿名类型解析为 int32

c# - 如何实现 "retry/abort"写入可能被其他进程使用的文件的机制?

c# - .NET FileSystemWatcher 在移动文件时进入无限循环

c# - 在 C# 中不使用 Exception 类的 Message 字段是一种好习惯吗?

c# - ASP.NET 页面生命周期 : How Page. ProcessRequest 执行事件和内部方法?

asp.net - 动画 ListView 页面更改

asp.net-mvc - EntityType 'ApplicantPosition' 没有定义键

xml - 将更新的 XMLDocument 保存为字符串(vb.net 或其他 .net 语言。)

mysql - 替代 EntityFunctions.AddSeconds for MySQL

c# - 列 ID 在规范中出现多次