[已编辑:我在下面留下了原始问题,并提供了更多上下文和代码来重现该问题。下面的简短版本包含问题的本质]
简短版本:下面的查询抛出 System.NotSupportedException:“无法将类型‘System.Linq.IOrderedQueryable1’转换为类型‘System.Linq.IQueryable
1’。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.IQueryable
1’。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/