2

これは、 ASP.NETのカスタムページングに関するこの質問のフォローアップです。

テーブルが定義されているとします。

CREATE TABLE Person
(
  ID int identity(1,1) not null primary key,
  FirstName varchar(50),
  LastName varchar(50)
)

そして、LinqtoSQLデザイナを介してクラスにマップしました。Personクラスでこのプロパティを定義しました:

public string Name
{
  get
  {
    if (FirstName != null && FirstName != "" && LastName != null && LastName != "")
      return String.Format("{0} {1}", FirstName, LastName);
    else if (FirstName == null || FirstName == "")
      return LastName;
    else if (LastName == null || LastName == "")
      return FirstName;
    else
      return "";
  }
}

そのNameプロパティにバインドされた列でソートされたグリッドがあり、ページングを実行したいとします。Linq to SQLを使用してこれを行う自然な方法は、次のようなものです。

MyDBContext db = new MyDBContext();
var myData = db.Persons.OrderBy(p => p.Name).Skip(pageSize * pageIndex).Take(pageSize);
myGrid.DataSource = myData;
myGrid.DataBind();

ただし、Linq to SQLは、NameプロパティをSQLに変換できないため、ここでエラーをスローします。.AsEnumerable()参照した質問への回答に記載されているように、フィルターの文字列を入力できますが、これは、すべての行をWebサーバーにプルしてそこで並べ替えることを意味します。これは、十分なレコードがある場合は理想的ではありません。テーブル。フィルタリングと並べ替えはデータベースで行う必要があります。

簡単な答えは、そのNameプロパティをSQLに変換し、データやビューなどを返すSPROCの一部にすることです。しかし、データベースレイヤーに表示ロジックを配置しているので、それは私には正しく感じられません。状況が私のやや不自然な例よりも複雑で、定義されたプロパティがより重要である場合は、さらに悪化します。

解決策はありますか、それともパフォーマンスと関心の分離のどちらかを選択する必要がありますか?それとも、データベース内のその種の表示ロジックに関する私の懸念は根拠がありませんか?

4

2 に答える 2

1

Name表示ロジックとデータベースの分離に関するご懸念は杞憂、というか、プロパティの背後にあるロジックが表示ロジックであるという考えは杞憂だと思います。

多くの場合、値は、表示目的のみであっても、クエリ、表示、および最適化を支援するために事前に計算されます。

IMO、Personsテーブルに呼び出された列が必要であり、他のプロパティをプロパティに変換し、残りのデータとともにそれを永続Name化するロジックがビジネスレイヤーに必要です。Name

次に、通常どおりにクエリを実行し、DB レベルで注文することができます (おそらく、データにはこれが役立つ他のケースもあります)。

ページングと並べ替えによって結果セットが管理可能なレベルにまでフィルター処理されたからといって、表示ロジックの操作を繰り返し実行しても問題ないというわけではありません。

別の考え方としては、変換と書き込みを数回行うということです。ただし、このデータを何度も読み取ることになり、毎回この変換を実行することになります。この変換の実行に費やされたすべての時間を合計すると、かなりの量になります。値を事前に計算し、必要なときに適切なクエリ操作を実行するだけで節約できる量です。

于 2011-08-16T17:44:31.283 に答える
1

LINQ to SQL はサーバー上でクエリと並べ替えを実行したいと考えています。これは、式が SQL に変換できる場合に実行できます。

コードはそのままでは翻訳できないため、エラーが発生します。

ただし、クエリをリファクタリングして名前を計算すると、次のように機能します。

var query = from p in db.Persons 
            let name = (p.FirstName + " " + p.LastName).Trim
            order by name  
            take 10
            select name;

これを実行してみると、LINQ-to-SQL がうまく変換してくれることがわかります。

SELECT [t2].[value]
        FROM (
            SELECT TOP (10) [t1].[value]
            FROM (
                SELECT LTRIM(RTRIM(([t0].[FirstName] + @p0) + [t0].[LastName])) AS [value]
                FROM [dbo].[Persons] AS [t0]
                ) AS [t1]
            ORDER BY [t1].[value]
            ) AS [t2]
        ORDER BY [t2].[value]

ただし、テーブルが大きくなる場合は、これをお勧めしません。理想的には一度実行して保存できる計算を繰り返し実行するように SQL に要求しています。結果を格納する計算フィールド FullName について考えてみましょう。これは計算を必要とせず、索引付けすることができます。

于 2011-08-16T17:43:23.193 に答える