10

この例を参照します:選択した指定された列を返す

引用: BlobDetails が LINQ エンティティでない場合は、直接実行できます。

var qry = from b in dc.Blobs
          orderby b.RowVersion descending
          select new BlobDetails {
              Id = b.Id, Size = b.Size,
              Signature = b.Signature, RowVersion = b.RowVersion};

return qry.ToList();

ORM ツールの LINQ TO SQL を使用して、クエリ内の特定の列を選択していることがわかります。ORM ツールの批評家は、私の記憶が正しければ、ORM ツールはテーブルからオブジェクト全体を選択して返し、従来の SQL プログラミングでできるように特定の列のみを選択するオプションを制限すると言います。もちろん、この例を見たとき、私はそれについて疑問を持っていますが、それにもかかわらず、データベースは選択された列のみを返すのか、それともオブジェクト全体を返し、列のフィルタリングをORMツール?

この例では、Blobdetails というクラスもあります。

public class BlobDetails   
{  
    public int Id { get; set; }  
    public string Signature { get; set; }  
    public int Size { get; set; }  
    public System.Data.Linq.Binary RowVersion { get; set; }     
}

LINQ を使用してテーブルからいくつかの列を選択するだけの場合、毎回独自のクラスを作成する必要がありますか?

4

4 に答える 4

14

テーブルからいくつかの列を選択するために、新しいクラスを作成する必要はありません。そのために匿名型を使用できます。

var qry = from b in dc.Blobs
          orderby b.RowVersion descending
          select new { b.Id, b.Size, b.Signature, b.RowVersion};

return qry.ToList();

選択した列のみが転送されます。プレーン SQL の使用と LINQ to SQL の使用に違いはありません。LINQ クエリを実行すると、プレーン SQL に変換されて実行されます。次に、結果がオブジェクトにマップされます。

SQL Server プロファイラーを使用して、サーバー上で生成および実行されたクエリを確認できます。また、LINQPadを使用して、クエリから生成される SQL を確認することもできます。あなたの場合、クエリは BlobDetails または匿名オブジェクトのどちらを使用しても同じになります。

SELECT [t0].[Id], [t0].[Size], [t0].[Signature], [t0].[RowVersion]
FROM [Blobs] AS [t0]
ORDER BY [t0].[RowVersion] DESC
于 2013-01-15T14:07:42.103 に答える
2

あなたの最初の質問に対する答えは、あなたが言及した POST にすでにあると思います。でも...

BlobDetailsLINQ エンティティでない場合は、selectステートメントでそれを使用して、射影属性を定義 (縮小) できます。例えば:

var qry = from b in dc.Blobs
          select new BlobDetails { Id = b.Id, Size = b.Size }

次のようなSQLクエリにコンパイルされますSELECT Id, Size FROM Blob ....

しかし、BlobDetailsLINQ エンティティである場合は、そのAsEnumerable()ハックを使用する必要があります。それ以外の場合はNotSupportedException: Explicit construction of entity type in query is not allowed.

var qry = from b in dc.Blobs.AsEnumerable()
          select new BlobDetails { Id = b.Id, Size = b.Size }

編集

@Chris Pitman がコメントで述べたようにAsEnumerable()、射影を適用する前にテーブル全体がメモリに読み込まれるため、このアプローチは深刻なボトルネックを引き起こす可能性があります。だからお勧めしません!

2 番目の質問に:

メソッドのスコープ外で簡単に使用したいオブジェクトのカスタム クラスを作成する必要があります。匿名オブジェクトのプロパティは、宣言されたスコープ内でのみ表示され、匿名オブジェクトは type にのみキャストできますobject

したがって、メソッドから匿名オブジェクトを返したい場合、戻り値の型は、@xeondev のコメントで述べたように列挙可能であるobject必要があります。dynamic

于 2013-01-15T13:52:58.147 に答える
2

射影を行うと、LINQ は実際にそれらの列のみを選択し、必要に応じて具体化することを妨げるものは何もありません。だからあなたのコード例では

select new BlobDetails 
{
  Id = b.Id, 
  Size = b.Size,
  Signature = b.Signature, 
  RowVersion = b.RowVersion
};

b.id、b.size、b.signature、および b.rowversion のみが選択されます。これは、SQL プロファイラーまたはデバッガーで確認できます。実行された最後のクエリを取得するためにデータコンテキストで呼び出すことができる関数もあると思います。

于 2013-01-15T13:54:08.507 に答える
1

独自のクラスを作成する必要はありません。匿名タイプを返すことができます。あなたはこのようなものを書くことができます

var qry = from b in dc.Blobs
          orderby b.RowVersion descending
          select new {
              Id = b.Id, Size = b.Size,
              Signature = b.Signature, RowVersion = b.RowVersion};

return qry.ToList();

メソッドのシグネチャは次のようになりますが

public  IEnumerable<object> GetItems()

また

public dynamic GetItems()

したがって、例が示すように、linqクエリの結果を外部スコープで使用する場合は、独自のクラスを作成することを強くお勧めします。

于 2013-01-15T12:53:48.910 に答える