2013-08-20 16 views
12

我一直試圖將LINQKit併入共享數據訪問層,但是,我遇到了障礙。在使用ExpandableQuery構造嵌套查詢時,表達式解析器無法正確解開ExpandableQuery並構造有效的SQL查詢。拋出的錯誤如下:LINQKit:將LINQ中的ExpandableQuery嵌套到實體

System.NotSupportedException:無法創建類型爲'Store'的常量值。只有原始類型或枚舉類型在此上下文中受支持。

通過下面的示例程序,我們可以很容易地重建這個問題,並且它明確地與表'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是你所期望的執行三角什麼加入:

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(),實體框架拉動整個賣場表進入內存之前,無法創建「無法創建常量」錯誤。

是否有任何已知的解決方法來強制LINQKit解開ExpandableQuery並評估表達式解析器中的嵌套子查詢?

回答

0

你可以嘗試的一件事是使用.AsEnumerable。這將防止直接轉換爲SQL,這是您的錯誤來自哪裏。

嘗試在你的主要如下:

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

這是不相關的Linqkit。當您使用只允許原始值的對象時,它總是會獲得EF異常。

我認爲tt是一個Store對象。該對象不能轉換爲SQL。因此,首先將ID tt.StoreId放入一個變量中並在查詢中使用該變量。