5

だから私の問題はこのようなものです。C#コードでは、入力パラメーターに応じて、LinqtoEntitiesを使用してエンティティセットの複数の順序付けを実行する必要があります。注文する列は3つあり、注文する列の順序自体は可変です(つまり、注文するたびに、注文する列を検索する必要があります)。どうすればこれを達成できますか?

動作するはずのコードがいくつかありますが、操作をパラメーター化できなかったため、繰り返しすぎています(Linq to Entitiesは、ラムダで許可されていることに対して非常に制限されています)。おそらくT4コード生成の助けを借りて、 DRYの原則に従ってコードを書き直す方法を提案してください。

次のコードは私の問題を説明するはずです。これは実際のコードの抜粋です。簡潔にするために、さらに含める必要があるかどうかをお知らせください。変数は「順序指定」のorderSpecs配列であり、それぞれが順序付けする列と降順で順序付けするかどうかを指定します。orderSpecs配列には少なくとも1つの要素があるため、少なくとも1つの順序付けが実行されます。

using (var db = new MyContainer())
{
    var orderSpec = orderSpecs[0];
    IQueryable<DbVersion> dVersions = null;
    if (orderSpec.Column == 0)
    {
        if (orderSpec.Descending)
        {
            dVersions = db.Versions.OrderByDescending(ver => ver.Name);
        }
        else
        {
            dVersions = db.Versions.OrderBy(ver => ver.Name);
        }
    }
    else if (orderSpec.Column == 1)
    {
        if (orderSpec.Descending)
        {
            dVersions = db.Versions.OrderByDescending(ver => ver.Built);
        }
        else
        {
            dVersions = db.Versions.OrderBy(ver => ver.Built);
        }
    }
    else if (orderSpec.Column == 2)
    {
        if (orderSpec.Descending)
        {
            dVersions = db.Versions.OrderByDescending(ver => ver.Id);
        }
        else
        {
            dVersions = db.Versions.OrderBy(ver => ver.Id);
        }
    }

    foreach (var spec in orderSpecs.Skip(1))
    {
        if (spec.Column == 0)
        {
            if (spec.Descending)
            {
                dVersions = dVersions.ThenByDescending(ver => ver.Name);
            }
            else
            {
                dVersions = dVersions.ThenBy(ver => ver.Name);
            }
        }
        else if (spec.Column == 1)
        {
            if (spec.Descending)
            {
                dVersions = dVersions.ThenByDescending(ver => ver.Built);
            }
            else
            {
                dVersions = dVersions.ThenBy(ver => ver.Built);
            }
        }
        else if (spec.Column == 2)
        {
            if (spec.Descending)
            {
                dVersions = dVersions.ThenByDescending(ver => ver.Id);
            }
            else
            {
                dVersions = dVersions.ThenBy(ver => ver.Id);
            }
        }
    }
4

2 に答える 2

16

これらの巨大なif-else構造をプロパティに引き起こしているこれらの列をマッピングするための辞書を作成するのはどうでしょうか。このように見える可能性があります:

using (var db = new MyContainer())
{
    var orderSpec = orderSpecs[0];
    IOrderedEnumerable<DbVersion> dVersions;

    var mapping = new Dictionary<int, Func<DbVersion, object>>()
    {
        { 0, ver => ver.Name },
        { 1, ver => ver.Built },
        { 2, ver => ver.Id }
    };

    if (orderSpec.Descending)
        dVersions = db.Versions.OrderByDescending(mapping[orderSpec.Column]);
    else
        dVersions = db.Versions.OrderBy(mapping[orderSpec.Column]);

    foreach (var spec in orderSpecs.Skip(1))
    {
        if (spec.Descending)
            dVersions = dVersions.ThenByDescending(mapping[spec.Column]);
        else
            dVersions = dVersions.ThenBy(mapping[spec.Column]);
    }
}
于 2012-05-11T11:00:50.153 に答える
3

Untypeの場合:動的Linqライブラリを使用することもできます:LINQ動的クエリライブラリを使用する

ここに画像の説明を入力してください

また

記事全文:GridView.OnSorting()を処理し、LINQを使用して動的に並べ替え式を作成する

タイプされた場合:以下のように動的ソートを実行して、作成したコードを削除できます

列名と並べ替え方向が固定されていないpersonというクラスでsoringを行う方法

IEnumerable<Person> persons = GetPersons();
    persons = persons.OrderBy(e.SortExpression, e.SortDirection);

人のクラス

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

データを並べ替えるための式ツリーを使用したジェネリックメソッド

public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> collection, 
       string columnName, SortDirection direction)
{
    ParameterExpression param = Expression.Parameter(typeof(T), "x"); // x
    Expression property = Expression.Property(param, columnName);     // x.ColumnName
    Func<T, object> func = Expression.Lambda<Func<T, object>>(        // x => x.ColumnName
        Expression.Convert(Expression.Property(param, columnName), 
        typeof(object)), param).Compile();

    Func<IEnumerable<T>, Func<T, object>, IEnumerable<T>> expression =
        SortExpressionBuilder<T>.CreateExpression(direction);
    IEnumerable<T> sorted = expression(collection, func);
    return sorted;
}
于 2012-05-11T10:48:51.780 に答える