EF4:LINQ 2实体查询工作在C#中,但不是在VB [英] EF4: LINQ 2 Entities query works in C# but not in VB

查看:118
本文介绍了EF4:LINQ 2实体查询工作在C#中,但不是在VB的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



短版:下面的查询将引发System.NotSupportedException:无法投类型'System.Linq.IOrderedQueryable 1为键入'System.Linq.IQueryable 1。LINQ到实体仅支持铸造实体数据模型基本类型。例外仅在VB.Net版本提高。当转换为C#,没有异常。

 暗淡doesThisCrash =从outerOrder订单
其中outerOrder.ProductId =
(从p在产品加入o在订单上p.Id等于o.ProductId
顺序按p.Id
选择p.Id).FirstOrDefault()
选择outerOrder
doesThisCrash.ToList()

所以,使其崩溃,我们似乎需要一个子查询这里原来的ObjectSet(订单)与另一个对象集(产品)加入,并下令。如果只使用订单或产品设置,不会发生崩溃。当离开了ORDER BY,还没有崩溃。



我倾向于认为这是一个(VB.Net)编译器缺陷,除非有什么明显的是我俯瞰这里...



现在我的问题依然存在:




  • 为什么在C#中一个看似完全相同的查询工作但不是在VB?

  • 可以此查询作出在VB.Net?



[/编辑]



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



我的域名看起来非常不同的,但我翻译的问题一个简单的版本,用下面的实体(注:其实,我定义了这些使用的.edmx设计,所以这是一个简化版本):

 公共类产品
{
公众诠释标识{搞定;组; }
公共字符串名称{;组; }
公众的DateTime dateCreated会获得{;组; }
}

公共类订单
{
公众诠释标识{搞定;组; }
公众诠释客户ID {搞定;组; }
公众诠释产品编号{搞定;组; }
公众的DateTime订购日期{搞定;组; }
}

公共类客户
{
公众诠释标识{搞定;组; }
}



我试图找出一个LINQ到实体查询应该strucurally这个样子,在VB.Net:

 暗淡DB =新SampleEntities()
昏暗的订单由于IQueryable的(秩序)= db.Orders
尺寸产品为IQueryable的(产品)= db.Products
昏暗的currentdate = DateTime.Now

尺寸qLinq =从outerOrder订单
其中outerOrder.OrderDate =的currentdate AndAlso运算
outerOrder.ProductId =
(从p在产品加入o在订单上p.Id等于o.ProductId
其中o.OrderDate = outerOrder。订购日期AndAlso运算
outerOrder.CustomerId = o.CustomerId
顺序按p.DateCreated
选择p.Id).FirstOrDefault()
选择outerOrder

这提出了一个System.NotSupportedException:



无法投型系统.Linq.IOrderedQueryable 1为键入'System.Linq.IQueryable 1。 LINQ到实体仅支持铸造实体数据模型的基本类型。



当离开了'ORDER BY'的一部分,不会引发异常。



我真的不明白为什么这个查询将不支持的理由。所以我决定尝试在C#一样的东西:



<订单
pre> VAR qLinq =从oOut那里oOut.OrderDate ==的currentdate
和;&安培; oOut.ProductId ==
(上接第在产品订单加盟澳上p.Id等于o.ProductId
,其中oOut.OrderDate == o.OrderDate
和;&安培; oOut.CustomerId == o.CustomerId
排序依据p.DateCreated
选择p.Id).FirstOrDefault()
选择oOut;

要我吃惊的是,这个作品!然后我翻译的C#查询扩展方法的语法,然后回VB,但得到了相同的结果(C#版本的作品中,VB.Net版本引发同样的异常)。



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




  • 为什么在C#中一个看似完全相同的查询工作但不是在VB?

  • 可以此查询作出在VB.Net?



作为参考,在这里是扩展方法的语法查询:



C#版本:

 变种q = orders.Where(outerOrder => 
outerOrder.OrderDate ==&的currentdate功放;&安培;
outerOrder.ProductId ==
(产品
。加入(订单,
F => f.Id,$ B $博=> o.ProductId,
(F,O)=>新建{F,O})
。凡(T => toOrderDate == outerOrder.OrderDate
和;&安培; outerOrder.CustomerId == toCustomerId)
.OrderByDescending(T => tfDateCreated)
。选择(T => tfId))
.FirstOrDefault());



VB.Net版本:

 暗淡q = orders.Where(功能(outerOrder)outerOrder.OrderDate =的currentdate AndAlso运算
outerOrder.ProductId =(products.Join(订单,
功能(p)页。 ID,
功能(O)o.ProductId,
功能(p,O)新增功能{p = p,的.o = O})
其中(功能(x)的XO订购日期= outerOrder.OrderDate AndAlso运算
outerOrder.CustomerId = xoCustomerId)
OrderByDescending(功能(X)xpDateCreated)
选择(功能(X)XPID)
FirstOrDefault()))


解决方案

移动顺序按p.DateCreated 行按我的编辑答案允许查询没有任何异常运行。但是,所发出的SQL是不同的,所以我不认为你找回正确的结果。

 暗淡qLinq =从outerOrder在订单
设ID =(从p在产品
顺序按p.DateCreated
加入o在订单上p.Id等于o.ProductId
其中o.OrderDate = outerOrder。订购日期AndAlso运算
outerOrder.CustomerId = o.CustomerId
选择p.Id).FirstOrDefault()
其中outerOrder.OrderDate =的currentdate AndAlso运算
outerOrder.ProductId = ID
选择outerOrder


[EDITED: I left the original question below, with some more context and code to reproduce the problem. The short version below contains the essence of the question]

Short version: the query below throws a System.NotSupportedException: "Unable to cast the type 'System.Linq.IOrderedQueryable1' to type 'System.Linq.IQueryable1'. LINQ to Entities only supports casting Entity Data Model primitive types." The exception is only raised in the VB.Net version. When translated to C#, no exception is raised.

   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()

So, to make it crash, it seems that we need a subquery where the original ObjectSet (orders) is joined with another ObjectSet (products), and ordered. When using just the orders or the products set, no crash occurs. When leaving out the Order By, also no crash.

I'm inclined to think this is a (VB.Net) compiler bug, unless there is something obvious that I'm overlooking here...

For now my question still stands:

  • why does a seemingly exact same query work in C# but not in VB?
  • can this query be made to work in VB.Net?

[/EDIT]

Optional, longer version (original question):

My domain looks very different, but I translated the problem to a simpler version, with the following entities (note: I actually defined these using the .edmx designer, so this is a simplified version):

    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; }
    }

I'm trying to work out a linq-to-entities query that should strucurally look like this, in VB.Net:

    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

This raises a System.NotSupportedException:

"Unable to cast the type 'System.Linq.IOrderedQueryable1' to type 'System.Linq.IQueryable1'. LINQ to Entities only supports casting Entity Data Model primitive types."

When leaving out the 'Order By' part, no exception is raised.

I don't really see a reason why this query would not be supported... So I decided to try the same thing in 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;

To my surprise, this works! Then I translated the C# query to extension method syntax, and then back to VB, but got the same results (the C# version works, the VB.Net version raises the same exception).

So I guess my question is twofold:

  • why does a seemingly exact same query work in C# but not in VB?
  • can this query be made to work in VB.Net?

For reference, here are the queries in extension method syntax:

C# version:

        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 version:

    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()))

解决方案

Moving the Order By p.DateCreated line as per my edited answer allows the query to run without any exceptions. However, the emitted SQL is different so I don't think you are getting back the correct result.

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

这篇关于EF4:LINQ 2实体查询工作在C#中,但不是在VB的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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