2016-08-11 4 views
0

タイトルはすべてそれを使用しようとしていますが、わかりません。問題は私がアマチュアであるために知識が不足している可能性がありますが、私はこの事について約12の質問を読んで3日間グーグルで調べましたが、それでも理解できません。Dapperのマッピング、マルチマッピング、QueryMultipleを理解できません

私は多くの質問をしているので、1つの質問だけですべてを書くべきか、誰かがそれをすべて読んでもよいとは思えません。誰かが他の解決策を持っている、あるいは私が別の質問でそれを分割すべきだと思うなら...まあ、私は提案に開放されています。

私は例を書こうとしていましたが、もう一度何十もの例を読み、私を助けませんでした。

私はちょうど私の心はgithubの時の例のようなものをどのように機能するかを理解するために作ることができない。

var sql = 
@"select * from #Posts p 
left join #Users u on u.Id = p.OwnerId 
Order by p.Id"; 

var data = connection.Query<Post, User, Post>(sql, (post, user) => { post.Owner = user; return post;}); 

ので、PostはタイプUserの性質を持っており、そのプロパティを右、Owner呼ばれているのですか?ような何か:

public class Post 
{ 
    ... 
    public User Owner { get; set;} 
} 

したがってQuery<Post, User, Post>は、すべてのプロパティと何ではないとPostインスタンスを返し、Userインスタンスを作成し、Post.Ownerプロパティに割り当てますか?たとえば、のようなIDを...WHERE Id = @Id", new {Id = id}のように渡したい場合など、単純なパラメータをどのようにクエリに追加すればよいでしょうか?パラメータが今すぐ(post, user) => { post.Owner = user; return post;}の場合は追加する必要がありますか?パラメータは常に指定された型を参照し、動的問合せには単純な典型的なパラメータのみを使用できますが、両方を同時に使用できますか?どうやって?

また、どのDBフィールドがどのオブジェクトになるのかを区別するにはどうすればよいですか?それはクラス名= DBテーブル名のようなものになりますか?クラスがDBテーブルと同じ名前を持たず、[Table]属性を使用したい場合はどうなりますか、それとも属性はDapper.Contrib.Extensionsメソッドのためだけですか?同じDBテーブルを共有するオブジェクトでも動作しますか?

異なるオブジェクトの同じテーブルに関する質問、f.i.

public class Person 
{ 
    ... 
    public BankAccount Account {get; set;} 
    ... 
} 

public class BankAccount 
{ 
    private string _Account; 

    public string Account 
    { 
     get { return _Account; } 
     set 
     { 
      if(!CheckIfIBANIsCorrect(value)) 
       throw new Exception(); 

      _Account = value; 
     } 
    } 

    private bool CheckIfIBANIsCorrect(string IBAN) 
    { 
     //... 
     //Check it 
    } 
} 

すべての人が人のIdで呼ばれる単一のアカウントを持っているであろうから、私は、Personより同じテーブルで文字列のアカウントを保存することができます:私はBankAccountオブジェクトを持っているPersonオブジェクトを持って言うことができます。どのようにマップする必要がありますか?方法はありますか?単に結果を動的オブジェクトにロードしてすべてのオブジェクトを作成すると、Queryオブジェクトの残りの部分が作成され、自分で入れ子オブジェクトを作成する必要がありますか?

ところで、splitOnはどうしてこの中で使われていますか? Ids f.iで結果を分割できるように、結果をさまざまな「グループ」に分割する必要があることを理解しています。あなたが必要とするものを取るが、私はどのように私は異なる "グループ"から情報を取得する必要があり、どのように別の "グループ"、リスト、列挙型、何を返すか理解していない。

QueryMultiple私が読んだ質問と回答のどれくらいが私の理解を超えてFARなのですか? あなたは知っているのですが、どうすれば.Readものが効くのですか?私がここで読んだこと、またはグーグルグーグルでは、Readは、オブジェクト間を奇妙に識別できる何らかのオートマチックなものだと仮定しています。繰り返しますが、クラス名で結果を分割するので、すべてのオブジェクトが正しいテーブル名を持つようにする必要があります。この場合、[Table]属性の場合はどうなりますか?

私は問題があると思うのですが(それは存在しないと思います)、それをすべて記述する単一のWebページ(GitHubの例は非常に乏しい)です。私が理解しようとしているものに正確に答えることのできない具体的なケースへの回答を見つけることができますが、それを読んでいるうちにますます混乱する具体的なケースだけです。どうやって。

答えて

1

Dapperが結合テーブルクエリをクエリする際の主な問題は、リストの2番目の引数が常に "param"引数であると考えていると思います。次のコードを考えてみましょう。ここでは

var productsWithoutCategories = conn.Query<Product>(
    "SELECT * FROM Products WHERE ProductName LIKE @nameStartsWith + '%'", 
    new { nameStartsWith = "a" } 
); 

を、二つの引数「SQL」と「paramが」がある - 私たちは名前付き引数を使用した場合、コードは次のようになります。

var productsWithoutCategories = conn.Query<Product>(
    sql: "SELECT * FROM Products WHERE ProductName LIKE @nameStartsWith + '%'", 
    param: new { nameStartsWith = "a" } 
); 

あなたの例では、あなたは

var data = connection.Query<Post, User, Post>(sql, (post, user) => { post.Owner = user; return post;}); 

にあなたがあなたのSQLクエリで2つのテーブルを参加した場合のためのエンティティを結合する方法Dapperのを告げる「マップ」と呼ばれる引数は実際にそこにある二番目の引数を持っています。私たちは名前付き引数を使用した場合、それは次のようになります。私は完全な例では、クラスNORTHWNDデータベースを使用するつもりだ

var data = connection.Query<Post, User, Post>(
    sql: sql, 
    map: (post, user) => { post.Owner = user; return post;} 
); 

using (var conn = new SqlConnection("Server=.;Database=NORTHWND;Trusted_Connection=True;")) 
{ 
    var productsWithCategories = conn.Query<Product, Category, Product>(
     "SELECT * FROM Products INNER JOIN Categories ON Categories.CategoryID = Products.CategoryID, 
     map: (product, category) => 
     { 
      product.Category = category; 
      return product; 
     }, 
     splitOn: "CategoryID" 
    ); 
} 

これは、すべての行を行く:私たちはクラス

public class Product 
{ 
    public int ProductId { get; set; } 
    public string ProductName { get; set; } 
    public bool Discontinued { get; set; } 
    public Category Category { get; set; } 
} 

public class Category 
{ 
    public int CategoryID { get; set; } 
    public string CategoryName { get; set; } 
} 

を持っていると言うと、我々は人口ネストされたカテゴリタイプで、製品のリストを構築したい、我々は次のようにしてくださいJOINされたProductとCategoryデータを取得し、一意のProductのリストを生成しますが、Categoryデータをどのように組み合わせるかを確かめることはできません。したがって、ProductインスタンスとCategoryインスタンスを取得し、 Categoryデータが結合されたProductインスタンス。この例では簡単ですが、ProductインスタンスのCategoryプロパティをCategoryインスタンスに設定するだけで済みます。

私は "splitOn"値を指定しなければならないことに注意してください。 Dapperは、テーブルのキー列を単に「Id」と呼び、そうであればそれらの列の結合を自動的に処理できると想定しています。しかし、この場合、「CategoryID」という列に参加しているため、その列名に従ってデータを(商品とカテゴリに)分割するようにDapperに指示する必要があります。

我々はまた、我々は次のように行うことができ、結果を絞り込むために「PARAM」オブジェクトを指定したい場合は:あなたの最後の質問に答えるために

var productsWithCategories = conn.Query<Product, Category, Product>(
    "SELECT * FROM Products INNER JOIN Categories ON Categories.CategoryID = Products.CategoryID WHERE ProductName LIKE @nameStartsWith + '%'", 
    map: (product, category) => 
    { 
     product.Category = category; 
     return product; 
    }, 
    param: new { nameStartsWith = "a" }, 
    splitOn: "CategoryID" 
); 

を、QueryMultipleは、単に一回で複数のクエリを実行あなたはそれを別々に読むことができます。たとえば、代わりにこれをやって(二つの別々のクエリで):

using (var conn = new SqlConnection("Server=.;Database=NORTHWND;Trusted_Connection=True;")) 
{ 
    var categories = conn.Query("SELECT * FROM Categories"); 
    var products = conn.Query("SELECT * FROM Products"); 
} 

あなたは1バッチ内の両方のクエリを含む単一のSQL文を指定することもできますが、あなたはその後、結合された結果のうち、それらを別々に読み込む必要がありますQueryMultipleから返されるセット:

using (var conn = new SqlConnection("Server=.;Database=NORTHWND;Trusted_Connection=True;")) 
{ 
    var combinedResults = conn.QueryMultiple("SELECT * FROM Categories; SELECT * FROM Products"); 
    var categories = combinedResults.Read<Category>(); 
    var products = combinedResults.Read<Product>(); 
} 

私は、彼らがしばしばある(という行のフルセットよりも、各クエリから単一の値を返すされているように私はQueryMultipleで見てきた他の例は少し混乱していると思います簡単なクエリ呼び出しでよく見られる)。だからうまくいけば、上記のことがあなたのためにクリアされます。

注:[Table]属性についての質問はまだありません。試しても問題が解決しない場合は、新しい質問を作成することをおすすめします。 Dapperは、 "splitOn"値を使用して、あるエンティティの終わりと次の開始の列を決定します(上記のJOINの例では、ProductのフィールドとCategoryのフィールドがあります)。 Categoryクラスの名前を他の名前に変更した場合、クエリは引き続き機能します.Dapperはこの場合はテーブル名に依存しません。[Table]は必要ありません。

+0

「クエリ」はちょうどオーバーロードされています。しかし、mapパラメータは、結合されたテーブルを持つクエリの場合にのみ使用されるか、または同じDBテーブルに格納されたネストされたクラスにデータを挿入するために使用できますか? F.i.私が質問した 'Person'の例、または同じ' Product' -'Category'を使って同じテーブルにすべてのデータを保存しています。 – Nox

+0

QueryメソッドでF12キーを押すと、すべてのオーバーロード、引数、およびドキュメンテーションのコメントを見ることができます。 1つのタイプのみのクエリ呼び出しのための "マップ"引数がありますが、これは個々のフィールドをプロパティにマッピングするためのものです。これは多くの手動作業です。 Dapperは、1つのテーブルからネストされたクラスへのマッピングをサポートしていません(Dapperの作者の回答http://stackoverflow.com/a/7523274/3813189を参照してください)。 –

+0

私はあなたの前にこのコメントを書いた、私はそれを読むでしょう。 – Nox

関連する問題