15

LINQKitを共有データ アクセス レイヤーに組み込むことを試みてきましたが、障害にぶつかりました。を使用してネストされたクエリを構築する場合ExpandableQuery、式パーサーは を正しくラップ解除しExpandableQueryて有効な SQL クエリを構築することができません。スローされるエラーは次のとおりです。

System.NotSupportedException : 'Store' 型の定数値を作成できません。このコンテキストでは、プリミティブ型または列挙型のみがサポートされています。

次のサンプル プログラムを使用すると、この問題を簡単に再構築でき、AsExpandable()`table.

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()、Entity Framework は、「定数を作成できません」というエラーで失敗する前に、ストア テーブル全体をメモリにプルします。

ExpandableQuery式パーサー内で入れ子になったサブクエリを強制的にアンラップして評価するように LINQKit に強制する既知の回避策はありますか?

4

2 に答える 2

1

試すことができることの 1 つは、.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();
于 2015-05-29T12:48:06.867 に答える
1

これは Linqkit とは関係ありません。これは、プリミティブ値のみが許可されているオブジェクトを使用するときに常に発生する EF 例外です。

tt物だと思いStoreます。このオブジェクトは SQL に変換できません。したがって、最初に IDtt.StoreIdを変数に入れ、その変数をクエリで使用します。

于 2016-06-12T15:57:30.583 に答える