我一直在尝试合并 LINQKit然而,我在共享数据访问层中遇到了障碍。使用 ExpandableQuery
构造嵌套查询时,表达式解析器无法正确解包 ExpandableQuery
并构造有效的 SQL 查询。抛出的错误如下:
System.NotSupportedException : Unable to create a constant value of type 'Store'. Only primitive types or enumeration types are supported in this context.
通过下面的示例程序,我们可以轻松地重构这个问题,并且它显然与 `table 上的 AsExpandable()
调用隔离。
class Program
{
static void Main(string[] args)
{
Database.SetInitializer<MyContext>(null);
var cs = MY_CONNECTION_STRING;
var context = new MyContext(cs);
var table = (IQueryable<Store>)context.Set<Store>();
var q = table
.AsExpandable()
.Select(t => new {Id = t.StoreId, less = table.Where(tt => tt.StoreId > t.StoreId) })
.Take(1)
.ToArray();
}
}
public class MyContext : DbContext
{
public MyContext(string connection) : base(connection) {}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Store>();
base.OnModelCreating(modelBuilder);
}
}
[Table("stores")]
public class Store
{
[Key]
public int StoreId { get; set; }
}
当您删除 AsExpandable()
调用时,生成的 SQL 就是您期望执行三角连接的 SQL:
SELECT
[Project1].[StoreId] AS [StoreId],
[Project1].[C1] AS [C1],
[Project1].[StoreId1] AS [StoreId1]
FROM ( SELECT
[Limit1].[StoreId] AS [StoreId],
[Extent2].[StoreId] AS [StoreId1],
CASE WHEN ([Extent2].[StoreId] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
FROM (SELECT TOP (1) [c].[StoreId] AS [StoreId]
FROM [dbo].[stores] AS [c] ) AS [Limit1]
LEFT OUTER JOIN [dbo].[stores] AS [Extent2] ON [Extent2].[StoreId] > [Limit1].[StoreId]
) AS [Project1]
ORDER BY [Project1].[StoreId] ASC, [Project1].[C1] ASC
但是,当您包含 AsExpandable()
时, Entity Framework 会将整个存储表拉入内存,然后因“无法创建常量”错误而失败。
是否有任何已知的解决方法可以强制 LINQKit 解开 ExpandableQuery
并计算表达式解析器中的嵌套子查询?
最佳答案
您可以尝试的一件事是使用.AsEnumerable。这将阻止直接转换为 SQL,而这正是错误的来源。
在 Main 中尝试以下操作:
var table = (IQueryable<Store>)context.Set<Store>();
var q = table
.AsEnumerable()
.Select(t => new {Id = t.StoreId, less = table.Where(tt => tt.StoreId > t.StoreId) })
.Take(1)
.ToArray();
关于LINQKit:在 LINQ to Entities 中嵌套 ExpandableQuery,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18346014/