5

私は Entity Framework 4.3.1 を使用しており、最初にコードを作成し、生成されているクエリを SQL プロファイラーで調べています。例を次に示します。

ご覧のとおり、引数をnvarchar(max)次のように指定していますが、私の構成ではMaxLength値を指定しています。したがって、パラメーターは次のように渡されると予想されますnvarchar(n) 。これを行わないため、クエリの実行が遅く、この単純な変更でクエリが高速化されることがわかりました。

Entity Framework に正しいnvarchar長さを生成させる方法を知っている人はいますか?

これが私のエンティティと構成コードです:

実在物

public class StorageTransportOrderItem 
{
    public string StorageTransportOrderItemNumber { get; set; }
    public string StorageNumber { get; set; }
    [...]
}

構成

ToTable("StorageTransportOrderItem");

Property(p => p.StorageTransportOrderNumber)
    .HasMaxLength(10);
Property(d => d.StorageTransportOrderItemNumber)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None)
    .HasMaxLength(4);

HasKey(d => new
{
    d.StorageTransportOrderItemNumber,
    d.StorageNumber,
    d.StorageTransportOrderNumber
 });

クエリの例

FROM [dbo].[StorageTransportOrder] AS [Extent1]
WHERE ([Extent1].[StorageNumber] = @p__linq__0) AND ([Extent1]
[StorageTransportOrderNumber] = @p__linq__1)
)  AS [Limit1]',N'@p__linq__0 nvarchar(max) ,@p__linq__1 nvarchar(max)  
',@p__linq__0=N'200',@p__linq__1=N'0001374850'

に注意してくださいnvarchar(max)。これが遅い原因です。

4

1 に答える 1

3

Tl:dr; Entity FrameworkHasMaxLength()を使用するときに制御できるものは何もないと思いますが、これを変更できるので、おそらくクエリを確認する必要があります。

私が思うこと

なぜあなたがクエリを取得しているのかについて少し混乱しています-それが私のテストシステムで取得しているものであるため、nvarchar(max)私は期待しています。nvarchar(4000)そして、この質問はそれについて尋ねます: コードファースト/EF は、生の SQL コマンドの文字列に「nvarchar(4000)」を使用するのはなぜですか? (かなり興味深い読書、それ)。ADO .Net のバージョンに関係があるのか​​もしれませんが、よくわかりません。

とにかく、私はあなたがこの価値に影響を与えることができないことを提案しようとしていると言っnvarchar(4000)nvarchar(max).

これらのクエリを生成するときに、Entity Framework は ADO .NET の自動パラメータ化機能を使用していると思います (参照: How Data Access Code Affects Database Performance )。基本的に、私は彼らが単純に ADO .NET に文字列値を追加し、それを処理しているのではないかと疑っていると言っていますDbParameter

あなたが指定したように、そのフィールドの長さを知っているので、これは本当に残念ですがMaxLength、ラムダ式のパラメーターとそれが関連する列を集計するのがどれほど複雑になるか想像できるので、私はそうではありません完全に驚いた。

何ができる?

これを変更することはできず、パフォーマンスには影響しますが、提案されているように、実行されるそのようなクエリの数を減らすことに集中することをお勧めします. 通常、このような些細なことではなく、クエリの構造とカウントを調整することによって、パフォーマンスを最大限に向上させることができます (単なる私の経験です。福音と見なさないでください)。

たとえば、ループ内で a のようなことを行っている場合は、おそらくそれをループ外でSingleOrDefault(i => i.id ==x)単一に変換する必要があります。Where(i => xs.Contains(i.id))そういうこと。具体的には言えませんが、適切なパフォーマンスを得るために他のアプローチを使用できると確信しています。

幸運を!

于 2013-10-18T10:11:10.617 に答える