Dapper.Rainbow(またはオプションでDapper.Contribを使用)を使用してナビゲーションプロパティを持つオブジェクトの挿入および更新を行う方法

dapper dapper-rainbow micro-orm orm

質問

私は最近Dapperを調べ始めました。私はそれをテストしており、基本的なCRUDを行うことができました。基本的な意味は、この構造のクラスで作業することです。

public class Product {
    public int Id {get;set;}
    public string Name {get;set;}
}

今では、挿入や更新を簡単に行うことができ、Dapper.Rainbowを見つけられるものを探していました。私はそれをチェックし、上記のようにオブジェクトを取得して挿入するためにそれを使用することができました。私の問題は、 Productにナビゲーションプロパティがある場合、そのフィールドに挿入することができないということです。だから私はこれを持っている:

public class Product {
    public int Id {get;set;}
    public string Name {get;set;}
    public ProductCategory Category {get;set;}
}

私はこれをすることができなくなります:

// connection is a valid and opened connection            
 var db = TestDatabase.Init(connection , 300);
 var newId = db.Products.Insert(newProduct);

この理由のために:

The member Category of type ProductCategory  cannot be used as a parameter value

Categoryint型(データベース内の同じデータ型)に置き換えると、問題は解決されます。しかし、それを行うと、(カテゴリー)Idだけでなく、そのカテゴリー情報で製品を照会することができなくなります。

生のDapperに頼らずに、ナビゲーションプロパティを持つクラスを使用して挿入と更新を行うにはどうすればよいですか?私は次のことができ、Dapper.Rainbowに挿入または更新時にCategoryを無視するように指示したいと考えていました。

public class Product {
    public int Id {get;set;}
    public string Name {get;set;}
    public ProductCategory Category {get;set;}
    public int CategoryId {get;set;} // this will be the same field name in the database
}

このシナリオは、NHibernateでCategoryプロキシオブジェクトを持つことができ、それをProduct割り当てて保存することができ、マッピングは完全に機能します。しかし、私はDapperを使いたいと思っています。それが私が探検しているところで、このようなことがどうやってできるのか学びたいのです。

受け入れられた回答

ダッパーではない。レインボー

これはDapper.Rainbowでは現在のフォームではできませんが、githubでプルリクエストを行うとこれが可能になります。

私は誰もDapper.Contrib使用を提案していないことに驚いています。私は機能がRainbowにあるかどうか尋ねた。しかし、私は誰もこの声明(特に太字のテキスト)に気付かれることは期待していませんでした。

今では、挿入や更新簡単に行うことができ、 Dapper.Rainbowを見つけられるものを探していました。私はそれをチェックし、上記のようにオブジェクトを取得して挿入するためにそれを使用することができました。私の問題は、Productにナビゲーションプロパティがある場合、そのフィールドに挿入することができないということです。

... Dapperライブラリに既に入っている代替案を提案します。私は私の質問ではっきりしていて、解決策がgithubにあるDapperライブラリ全体のどこかに存在するかどうかを明示的に尋ねたはずです。図書館をもっと掘り下げた後、私は自分の問題を支持していることを知りました。

Dapper.Contribへのパス

私がもっと必要とするまで、すべて私のプロジェクトとRainbowうまくいきます。そこにはたくさんの畑があるテーブルがあります。私がレインボーを私のオブジェクトにちょうどフィードしたら、それはすべてのフィールドで更新を行いますが、それはすべて良いわけではありません。しかし、それは私がボートからすぐに飛び降りてNHに戻ることを引き起こしません。だから自分のchange trackingを実装する前に、特に誰かがうまく仕事をしていれば、私は車輪を再発明したくないです。私は周りを見つけて、このSOスレッド見つけました 。そのスレッドは、 Rainbowがチェンジトラッキングをサポートしていないことを確認しましたが、もう1つの獣があり、それはDapper.Contribと呼ばれていDapper.Contrib 。そして私はそれを試し始めました。

そして私たちは再び会う

ProductCategoryタイプのメンバーCategoryをパラメータ値として使用することはできません

私はRainbowと同じ問題を抱えていました。 Contribはナビゲーションプロパティをサポートしていません!私はDapperで自分の時間を無駄にしていると感じ始めています。私が大いに後にしている、それが提供するパフォーマンスはちょうど希望的な考えになります。まで...

WriteAttributeは、救助に来た...

このクラスは、 Dapper.Contribプロジェクトに含まれているSqlMapperExtensions.csファイルにSqlMapperExtensions.csます。私はこのクラスについての文書も見つけられませんでしたし、それが簡単に見つけて私に叫んでhey I'm the one you're looking forと言うことができるコメントがありません。私が上記のようにRainbowを脇に置いたとき、私はこれを見つけました。

このクラスの使い方は、 IgnorePropertyAttributeで行ったのと同じです。クラスのプロパティを修飾する属性です。この属性を使用して、 Dapperが作成するsqlには含めたくないプロパティをデコレートする必要があります。だから私の例では、DapperにCategoryフィールドを除外するように指示するために、私はこれを行う必要がありました:

public class Product {
    public int Id {get;set;}

    public string Name {get;set;}

    [Write(false)] // tell Dapper to exclude this field from the sql
    public ProductCategory Category {get;set;}

    public int CategoryId {get;set;}
}

私はほとんどそこにいる

私がContribに行く理由は、 change tracking機能のためです。 このSOスレッドは、上記で示したリンクと同じですが、変更トラッキングを開始するには、クラス用のインターフェイスが必要で、 Contribと共に使用する必要があります。私のクラスの例では、

public interface IProduct {
    int Id {get;set;}
    string Name {get;set;}
    ProductCategory Category {get;set;}
    int Category {get;set;}
}

// and implement it on my Product class
public class Product : IProduct {
    public int Id {get;set;}

    public string Name {get;set;}

    [Write(false)]
    public ProductCategory Category {get;set;}

    int Category {get;set;}
}

私はそれがほとんどだと思った! Dapperがまったく気にしないのであれば、なぜ私は自分のインターフェースにCategoryを定義する必要があるのか​​尋ねているかもしれません。実際にそれは問題を引き起こすだけで、私はそれを解決することができます。

私の特定のシナリオでは、 Productオブジェクトの変更トラッキングを維持しながらCategoryフィールドを操作する必要があることがあります。トラッキング機能を維持するには、getコールに次のようなインタフェースタイプを指定する必要があります。

var product = connection.Get<IProduct>(id);

その呼び出しで、私はアクセスすることはできません Category 、私は私のインターフェイスでそれを定義しない場合、フィールドを。しかし、私は私のインターフェイスでそれを定義する場合、私はよく知られているエラーを取得します

タイプ{type}のメンバー{member}をパラメーター値として使用することはできません。

本当にもう一度?これをやめてください。

評決

このクラスのために行ったことと同じように、インターフェイスメンバーをデコレートすることで、これを解決するのが簡単なので心配する必要はありません。したがって、すべての作業を行うための最終的な設定は、次のとおりです。

public interface IProduct {
    // I will not discuss here what this attribute does
    // as this is documented already in the github source.
    // Just take note that this is needed,
    // both here and in the implementing class.
    [Key]
    int Id {get;set;}

    string Name {get;set;}

    [Write(false)]
    ProductCategory Category {get;set;}

    int Category {get;set;}
}

// and implement it on my Product class
public class Product : IProduct {
    [Key]        
    public int Id {get;set;}

    public string Name {get;set;}

    [Write(false)]
    public ProductCategory Category {get;set;}

    int Category {get;set;}
}

change tracking機能を持つContribで作業しContrib場合は、この方法を使用できます。 Rainbowと仕事をしたいと思っていて、私が持っていたのと同じようにナビゲーションプロパティに問題がある場合は、プルリクエストで遊ぶことができます。これは、同じように動作WriteAttributeそれはで動作することを唯一のRainbow

属性でクラスを装飾するファンでなければ、両方の拡張プロジェクトはあなたのためではありません。私はあなたが流暢型の構成のいくつかの種類に行うことができます別の拡張プロジェクトがあることを知っているが、それは(のコア一部として含まれていない)に行かない Dapper githubの中にあるライブラリ。私の好みは、コアライブラリのみで動作することです。ライブラリ全体を調査して、すでにそこにあるかどうか、私のニーズを満たすために改善できるかどうかを確認します。そして、それは私がRainbowContrib両方のためにここでContribです。

この貢献、私が追加した非常にシンプルなクラス、私が示した設定のヒント、それらを導くシナリオは、将来Dapperを使いたい人を助け、私の持つ同様の設定になることを願っています。また、この答えは、Dapperが行うことができることと行えないことの両方をdevsに教えるでしょう。 Dapperと呼ばれるこの素晴らしいツール は、より良いwikiにふさわしいと私はこの答え/ここでの記事は、ほんの少しでも役立つことを願っています。


**そして私がここに書いたものがすでにどこかに書かれていて、2週間の時間内に私が答えを待っていることが分かっていないなら、誰かが私をそれにリンクさせることができてうれしい。 2週間ほど経っていて、私の質問に目を通した29人がリンクや解決策を提案していないので、私がここで共有した情報はDapper *にとって初めてのものだと思った

注:私は自分の質問のタイトルを変更して、他の人が自分の問題に対するこの潜在的な解決策を見られるようにしました。新しいタイトルは、Dapperについて私が得た新しい知識に基づいています。



ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow