16

私は以下のコードを持っています:

using (DBContext context = new DBContext())
{
    myCollection = context.Items.Where(i => i.Type == 1).OrderBy(k => k.Name).Select(w => new
    {
        Alias = w.Name + string.Format("{0}", w.Id),
        Name = w.Name                        
    }).ToArray();
}

実行時に、文字列を連結しようとしてエラーが発生し、整数 w.Id を文字列に変換しようとするとエラーが発生します。

エラーは言う:

エンティティへの Linq はメソッド string.Format を認識しません

また、プラス連結記号「+」はサポートされていません。

AsEnumerable を導入することでこれを解決しました。

using (DBContext context = new DBContext())
{
    myCollection = context.Items.AsEnumerable().Where(i => i.Type == 1).OrderBy(k => k.Name).Select(w => new
    {
        Alias = w.Name + string.Format("{0}", w.Id),
        Name = w.Name                        
    }).ToArray();
}

しかし、これが最善の解決策であるか、これを行うのに適した別の方法があるかどうかを知りたいです。アイデア?

4

2 に答える 2

19

EF はString.FormatSQL に変換できませんが、文字列の連結は問題なく処理できます。サーバー側で数値を文字列に変換するSqlFunctions.StringConvert代わりに使用します。String.Format

Select(w => new {
    Alias = w.Name + SqlFunctions.StringConvert((double)w.Id),
    Name = w.Name                        
})

次のようなものを生成します

SELECT 
[Extent1].[Name] + STR( CAST( [Extent1].[Id] AS float)) AS [C1], 
[Extent1].[Name] AS [Name]
FROM [dbo].[Items] AS [Extent1]

更新: したがって、この変換をサポートしない EF プロバイダーを使用しています (SQL CE プロバイダーはこのクエリを SQL に変換できません) 1 つのオプションしか残っていません - 既に行ったように、計算をクライアント側に移動します。

于 2013-10-02T22:27:07.260 に答える
17

コードの最適化の 1 つは、メソッドAsEnumerable()の後に使用することです。Whereそうでない場合は、すべてのエンティティがストレージから返され、テーブル全体が LINQ to Objects を使用して調べられます。コードをこのように単純に変更すると、SQL で where 句を実行できるようになり、ストレージから取得するレコードが少なくなります。一般的なルールは、LINQ プロバイダーによって実装されるすべてのクエリ句を最初に配置することです。

using (DBContext context = new DBContext())
{
    myCollection = context.Items.Where(i => i.Type == 1)
       .AsEnumerable().OrderBy(k => k.Name).Select(w => new
        {
            Alias = w.Name + string.Format("{0}", w.Id),
            Name = w.Name                        
        }).ToArray();
}
于 2013-10-02T23:02:41.403 に答える