4

次のようなLinqステートメントで(質問に関連する部分に絞り込まれています):

var sites = from s in DataContext.Sites
            join add in DataContext.Address 
              on s.PrimaryAddress equals add into sa
    from a in sa.DefaultIfEmpty()
            select new {
                        s.Id,
                        s.SiteName,
                        PrimaryAddress = a
                       };

問題は、最終的に GridView/LinqDataSource の組み合わせに基づくコントロールが、PrimaryAddress 結合クラスで正しく並べ替えられない (無視される) ことです。このように、結合されたすべてのクラスで同じ動作が見られます。GridView がこれを処理する方法はありますか? または、式を介して動的な OrderBy のコードで処理できる方法はありますか?

追加メモ: 追加するとき.OrderBy(s => s.PrimaryAddress)は getCannot order by type 'Address'を、実行.OrderBy(gs => gs.PrimaryBusinessAddress.AddressLine1)するときは get Specified method is not supported. LinqDataSource.OrderBy 自体で並べ替えを行うと、手遅れです...現在のページのレコードのみを並べ替え、セット全体では並べ替えません。

わかりやすくするために、これはグリッド内のアドレスの形式です。

public partial class Address
{
  public override string ToString()
  {
    return string.Format("{0} {1}{2} {3}",
    AddressLine1,
    City,
    !string.IsNullOrEmpty(State) && State != "None" ? ", " + State : string.Empty,
    !string.IsNullOrEmpty(Country) ? string.Format("({0})", Country) : string.Empty);
  }
}

で並べ替えることができればAddressLine1 + City + State + Country十分ですが、式ツリーを介してこれを行う方法がわかりません...式で指定した OrderBy に関係なく、s.SiteNameによる並べ替えに戻ります(デフォルトの並べ替えグリッド上)。グリッド コントロールに表示される、このように結合されたクラスの数は非常に限られていますが、それぞれにスイッチと Expression ケースを使用してもまったく問題はありません。解決策、またはまったく異なるアプローチについて何か考えはありますか?

4

3 に答える 3

3

私はコードで Linq to Entities を使用することに慣れていますが、LINQPad で LINQ to SQL を頻繁に使用するので、かなり慣れてきました。どこで問題が発生しているのか完全にはわかりませんが、次の方法でうまくいくと思います。

var sites = from s in DataContext.Sites
            orderby s.PrimaryAddress.AddressLine1,
                     s.PrimaryAddress.City,
                     s.PrimaryAddress.State,
                     s.PrimaryAddress.Country
            select new 
            {
                s.Id,
                s.SiteName,
                s.PrimaryAddress
            };

私が理解していないことがあれば教えてください。

アップデート

なぜこれがうまくいかないのかわかりません。LINQPad (LINQ to SQL モード) で次のことを行いました。

from p in person
orderby p.clue_type.clue_type_id,
        p.clue_type.clue_type
select new
{
    p.person_id, p.clue_type
}

結果はすべてclue_type = nullでした。LINQ to SQL では、null 参照がすべて null のプロパティを持つ値として扱われます。生成された SQL は次のとおりです。

SELECT TOP (10) [t0].[person_id], [t2].[test], [t2].[clue_type_id], [t2].[clue_type]
FROM [person] AS [t0]
LEFT OUTER JOIN (
    SELECT 1 AS [test], [t1].[clue_type_id], [t1].[clue_type]
    FROM [clue_types] AS [t1]
    ) AS [t2] ON [t2].[clue_type_id] = [t0].[clue_type_id]
ORDER BY [t2].[clue_type_id], [t2].[clue_type]

LEFT OUTER JOIN に注意してください。これはあなたが求めていることをしませんか?

更新 2

どの程度動的にするかによっては、クエリを動的にするのはかなり難しい場合があります。メソッドに渡される文字列値に基づいて、返すプロパティのいずれかで順序付けできるようにする場合の解決策の 1 つを次に示します。

public class SiteDisplayInfo
{
    public int Id {get;set;}
    public string SiteName {get;set;}
    public string PrimaryAddress {get;set;}

    public static readonly Dictionary<string, Func<IQueryable<Site>, IOrderedQueryable<Site>>> OrderByFuncs = 
    new Dictionary<string, Func<IQueryable<Site>, IOrderedQueryable<Site>>>
    {
        {"Id", q => q.OrderBy(s => s.Id)},
        {"SiteName", q => q.OrderBy(s => s.SiteName)},
        {"PrimaryAddress", 
        q => q.OrderBy(s => s.PrimaryAddress.AddressLine1)
                             .ThenBy(s => s.PrimaryAddress.City)}
    };
}

...

public IEnumerable<SiteDisplayInfo> GetSites(string orderByString)
{
    IQueryable<Site> sites = DataBase.Sites;
    if (orderByString != null && SiteDisplayInfo.OrderByFuncs.ContainsKey(orderByString))
    {
        sites = SiteDisplayInfo.OrderByFuncs[orderByString](sites);
    }
    var query = from s in sites
                select new SiteDisplayInfo
                {
                    Id = s.Id,
                    SiteName = s.SiteName,
                    PrimaryAddress = s.PrimaryAddress.AddressLine1 + s.PrimaryAddress.City
                };
    return query.ToList();
}

似たようなことを行う方法は他にもいくつかありますが、これで一般的な考え方がわかります。

于 2009-09-30T19:58:05.120 に答える
2

私はあなたが持っているものと同様のセットアップを試しました、これはうまくいくはずです:

var sites = from s in dc.Sites
    join addr in dc.Addresses
        on s.PrimaryAddress equals addr into sa
    from a in sa.DefaultIfEmpty()
    orderby a.AddressLine1, a.City, a.State, a.Country /* insert orderby here */
    select new
        {
            s.Id,
            s.SiteName,
            PrimaryAddress = a
        };

orderbyの方向を変更する場合は、すべての列に降順を追加するだけです。

orderby a.AddressLine1 descending, a.City descending, a.State descending, a.Country descending

このアプローチは機能しますが、正確には動的ではありません。別の方向または列の順序で並べ替えるには、クエリを書き直す必要があります。

これが必要な場合は、追加の配管を使用するメソッドアプローチ、または列名をリテラルとして指定できる動的OrderByを使用する完全に動的なアプローチのいずれかを使用することをお勧めします。後者については、このトピックとこのブログ投稿を確認してください。

于 2009-10-02T11:38:55.950 に答える
0

.OrderBy(s => s.PrimaryAddress) を追加すると、タイプ '住所' で注文できません

これは、PrimaryAddress がコード内にのみ存在するためです。LINQ ステートメントは、アドレスを作成するためにすべての行を取得し、それらをコードでマージします。何らかの形式の .OrderBy(a => a.Address) を試しましたか? つまり、派生名の代わりにサブテーブルの列を参照します。

于 2009-09-25T12:35:18.953 に答える