15

以下のアプローチに従って、LINQ To SQL を使用して複数の結果からデータを取得しました。

CREATE PROCEDURE dbo.GetPostByID
(
    @PostID int
)
AS
    SELECT    *
    FROM      Posts AS p
    WHERE     p.PostID = @PostID

    SELECT    c.*
    FROM      Categories AS c
    JOIN      PostCategories AS pc
    ON        (pc.CategoryID = c.CategoryID)
    WHERE     pc.PostID = @PostID

DataContext から継承するクラスの呼び出しメソッドは次のようになります。

[Database(Name = "Blog")]
public class BlogContext : DataContext
{
    ... 

    [Function(Name = "dbo.GetPostByID")]
    [ResultType(typeof(Post))]
    [ResultType(typeof(Category))]
    public IMultipleResults GetPostByID(int postID)
    {
        IExecuteResult result = 
            this.ExecuteMethodCall(this, 
                  ((MethodInfo)(MethodInfo.GetCurrentMethod())), 
                  postID);

        return (IMultipleResults)(result.ReturnValue);
    }
}

このメソッドは、ストアド プロシージャ名にマップされる Function 属性だけでなく、ストアド プロシージャが返す結果セットの型を持つ ReturnType 属性でも修飾されていることに注意してください。さらに、メソッドは IMultipleResults の型指定されていないインターフェイスを返します。

public interface IMultipleResults : IFunctionResult, IDisposable
{
    IEnumerable<TElement> GetResult<TElement>();
}

そのため、プログラムはこのインターフェイスを使用して結果を取得できます。

BlogContext ctx = new BlogContext(...);

IMultipleResults results = ctx.GetPostByID(...);

IEnumerable<Post> posts = results.GetResult<Post>();

IEnumerable<Category> categories = results.GetResult<Category>();

上記のストアド プロシージャでは、2 つの選択クエリがありました。 1. 結合なしの選択クエリ 2. 結合ありの選択クエリ

ただし、上記の 2 番目の選択クエリでは、表示されるデータはテーブルの 1 つ、つまり Categories テーブルからのものです。しかし、結合を使用して、両方のテーブル、つまりカテゴリと PostCategories からの結果を含むデータ テーブルを表示したいと考えています。

  1. LINQ to SQL を使用してこれを達成する方法を教えてください。
  2. 単純な SQL で上記のアプローチを実装するのに対して、上記のアプローチを使用した場合のパフォーマンスのトレードオフは何ですか?
4

3 に答える 3

9

Scott Guthrie (MS で .Net 開発チームを率いる人物) は、数か月前に彼のブログでこれを行う方法を私よりもはるかにうまく説明しまし。そのページには、「SPROC からの複数の結果形状の処理」というタイトルのセクションがあります。これは、異なる形状 (または同じ形状) のストアド プロシージャからの複数の結果を処理する方法を説明しています。

彼の RSS フィードを購読することを強くお勧めします。彼は、 .Netに関するすべてのことについて、ほぼ権威ある情報源です。

于 2008-12-16T14:59:06.253 に答える
7

ちょっとおい - これはうまくいきますか?

IEnumerable<Post> posts;
IEnumerable<Category> categories;

using (BlogContext ctx = new BlogContext(...))
{
    ctx.DeferredLoadingEnabled = false; // THIS IS IMPORTANT.
    IMultipleResults results = ctx.GetPostByID(...);
    posts = results.GetResult<Post>().ToList();
    categories = results.GetResult<Category>().ToList();
}
// Now we need to associate each category to the post.
// ASSUMPTION: Each post has only one category (1-1 mapping).
if (posts != null)
{
    foreach(var post in posts)
    {
        int postId = post.PostId;
        post.Category = categories
            .Where(p => p.PostId == postId)
            .SingleOrDefault();
    }
}

Ok。これを分解しましょう。

最初に、using ブロック内で適切な接続を行います (適切に破棄されます)。

次に、DEFERRED LOADINGoffであることを確認します。それ以外の場合は、セットを実行しようとすると (例post.Category == blah)、それが null であることがわかります。データを遅延ロードし(例: データベースを往復する)、データを設定し、データベースからドラッグしたばかりのものをオーバーライドします。 thereWhere(..)メソッドの結果。ふぅ!概要: クエリの範囲で遅延読み込みがオフになっていることを確認してください。

最後に、投稿ごとに、2 番目のリストからカテゴリを反復して設定します。

それは役に立ちますか?

編集

メソッド呼び出しで列挙エラーにならないように修正しましたToList()

于 2009-01-20T05:42:43.093 に答える
0

Post に 1 つまたは複数のカテゴリがある場合、for ループを使用する代わりに、JOIN を使用して Post.PostCategories にカテゴリのリスト (1 対多) をすべて 1 回でロードすることは可能ですか?

var rslt = from p in results.GetResult<Post>()
           join c in results.GetResult<Category>() on p.PostId = c.PostID
           ...
           p.Categories.Add(c)
于 2010-12-20T13:51:36.743 に答える