2

私はこれから始めています:

query
    .Take(20)
    .Select(item => new
    {
        id = item.SomeField,
        value = item.AnotherField
    })
    .AsEnumerable()
    .ToDictionary(item => item.id, item => item.value);

ここで、 と を除くすべてを再利用したいと思いSomeFieldますAnotherField

public static Dictionary<int, string> ReusableMethod<T>(
    this IQueryable<T> query,
    Func<T, int> key,
    Func<T, string> value)
{
    return query
        .Take(20)
        .Select(item => new
        {
            id = key(item),
            value = value(item)
        })
        .AsEnumerable()
        .ToDictionary(item => item.id, item => item.value);
}

query.ReusableMethod(item => item.SomeField, item => item.AnotherField);

これは機能しますが、DB クエリは必要以上のデータを選択するため、ReusableMethodlinq-to-objects を使用していると思います。

必要なデータのみを選択しながらこれを行うことは可能ですか? Func<> はまだ私にとって魔法の一部であることを付け加えます。そのため、明らかな何かが欠けている可能性があります。

混乱を避けるための明確化Take(20):は問題ありませんが、そうでSelect()はありません。

4

2 に答える 2

3

関数をラップしExpressionて呼び出しを削除しAsEnumerableます。

 public static Dictionary<int, string> ReusableMethod<T>(
    this IQueryable<T> query,
    Expression<Func<T, int>> key, 
    Expression<Func<T, string>> value)

別の方法は、行全体を返すことです。Expressionこの場合は必要ありません。

return query
    .Take(20)
    .ToDictionary(key, value);
于 2012-11-27T14:37:21.020 に答える
1

最近、私は同じ問題を抱えていました。これが私がしたことです:

  1. いくつかの DbEntity (LINQ to EF、SQL によって生成されたもの) がありますが、いくつかのフィールドのみを照会したい (ネットワーク帯域幅を節約するためにこれを行いました)。式ツリーで匿名型を作成できず、select ステートメントで DbEntity の新しいインスタンスを作成できないため、DbEntity から派生したクラスを作成する必要があります。(フィールド、プロパティなどを追加する必要はありません)

    public class LocalEntity : DbEntity {}

  2. 選択式ツリーを生成するメソッドを定義する必要があります。このように見えるはずです。これにより、次のような式ツリーが生成されます: .Select(db => new LocalEntity() { Property1 = db.Property1, Proeprty2 = db.Property2})

    protected Expression<Func<DbEntity, LocalEntity>> getSelectExpression()
    {
        ParameterExpression paramExpr = Expression.Parameter(typeof(DbEntity), "dbRecord");
        var selectLambda = Expression.Lambda<Func<DbEntity, LocalEntity>>(
                            Expression.MemberInit(
                                Expression.New(typeof(LocalEntity)),
                                Expression.Bind(typeof(LocalEntity).GetProperty("DbEntityFieldName"), Expression.Property(paramExpr, "DbEntityFieldName"),
                                ....
                                ))
                            ),
                            paramExpr);
    
        return selectLambda;
    }
    
  3. 次のように使用します。

    query.Select(getSelectExpression()).ToDictionary();

これは C# コードというより疑似コードと考えてください。大幅に単純化する必要があり、テストすることはできませんが、動作させると、行全体ではなく、getSelectedExpression で定義したフィールドのみが DB から転送されます。 .

于 2012-11-27T15:56:45.977 に答える