2011-08-05 7 views
0

複合主キー(Azureテーブル、主キーは(PartitionKey、RowKey))を持つテーブルに対してFluent-nHibernateを使用する必要があります。流暢なnHibernateのためのコンベンションによる複合プライマリキー宣言

{ 
    PartitionKey PK, 
    RowKey PK, 
    [..] 
} 

と実体

public class MyRecord 
{ 
    public virtual string PartitionKey{get;set;} 
    public virtual string RowKey{get;set;} 

    [...] 
} 

マイ:エンティティ(またはコンポーネントプロパティを持つ、より簡単にする場合)

に私のテーブルには、次のようになります現在のprojetは、AzureTableをターゲットとするカスタムnHibernate Driverを使用します。

私はそれがClassMapまたはXMLマッピングで動作するように管理しました。したがって、私はドライバーが働いていると確信しています。さらに、AzureテーブルのHTTPリクエストは、クラスマップまたはXML宣言を使用して正しいものです。

しかし、私は本当に慣習が必要なので、これは容認できる解決策ではありません。

最後に、Datastoreが(PartitionKey、RowKey)を使用する場合でも、RowKeyのみをPKとしてマップするオプションが常にあります。それも動作しますが、nHibernateと基礎となるデータストアの間のユニティシュアル処理の不一致が導入されるため、実際には満足できるものではありません。

UPDATE:

私は、カスタムIIdentityConventionを構築しようとしました。 IIdentityInstance.Column()メソッドは、最初の呼び出しのみを考慮に入れます。 しかし、リフレクションを使用して両方の列を基になるマッピングフィールドに追加すると、XML検証例外(属性 'クラス'が必要)でコンフィグレーションビルドが失敗します(属性 'クラス'が必要です)

答えて

1

今日はうまくいきました。また、慣例も使用しません。私は規則を理解しているので、実際には、メインマッピングが行われた後に、それらを調整するためのものです。私が考えているマッピングを追加することは、慣習の範囲外と考えられます。

私のプロジェクトでは、型の知識はなく、コンポジットキーの依存関係が埋め込まれたマッピングのオーバーライドを持つ汎用の自動マッピングベースの初期化プロシージャがあります。厳密にはあなたのシナリオではありませんが、同様の問題です。

私がリフレクションを通して動作させる方法は、適切なAutoPersistenceModelオブジェクトを取得することでした。あなたは、コードのように探している場合:ここから

Fluently.Configure().Mappings(m => ... 

AutoPersistenceModelオブジェクトはm.AutoMappings.First(だろう)

を、それがFluentNHibernate内部の保護されたメソッドの呼び出しで最高潮に達する、かなり深刻反射仕事です。ここに私が使用しているコードはあります:

private void Override(AutoPersistenceModel container, 
          Type type, 
          IEnumerable<KeyValuePair<string,string>> compositeKeys) 
    { 
     // We need to call container.Override<T>(Action<Automapping<T>> populateMap) 
     // Through reflection...yikes 
     var overrideMethod = typeof(AutoPersistenceModel) 
           .GetMethod("Override") 
           .MakeGenericMethod(type); 
     var actionFactoryMethod = typeof(FluentNHibernateInitializer) 
            .GetMethod("CompositeMapperFactory", 
             BindingFlags.Instance | BindingFlags.NonPublic) 
            .MakeGenericMethod(type); 
     var actionMethod = actionFactoryMethod 
          .Invoke(this, new object[] { compositeKeys }); 
     overrideMethod.Invoke(container, new object[] {actionMethod}); 
    } 

    private Action<AutoMapping<T>> CompositeMapperFactory<T> 
      (IEnumerable<KeyValuePair<string, string>> compositeKeys) 
    { 
     return new Action<AutoMapping<T>>(m => 
      { 
       var compositeId = m.CompositeId(); 
       foreach (var kvp in compositeKeys) 
        compositeId = 
         AddKeyProperty(
         compositeId, 
         typeof(T).GetProperty(kvp.Key), 
         kvp.Value); 
      } 
     ); 
    } 

    /// <summary> 
    /// Uses reflection to invoke private and protected members! 
    /// </summary> 
    /// <param name="compositeId"></param> 
    /// <param name="propertyInfo"></param> 
    /// <returns></returns> 
    private CompositeIdentityPart<T> AddKeyProperty<T> 
     (CompositeIdentityPart<T> compositeId, 
     PropertyInfo propertyInfo, 
     string column) 
    { 
     var member = FluentNHibernate.MemberExtensions.ToMember(propertyInfo); 
     var keyPropertyMethod = typeof(CompositeIdentityPart<T>) 
            .GetMethod("KeyProperty", 
            BindingFlags.Instance | BindingFlags.NonPublic); 
     return (CompositeIdentityPart<T>) 
       keyPropertyMethod 
        .Invoke(compositeId, new object[] { member, column, null }); 
    } 
+0

ありがとう!それは私が最終的に私のAzureテーブルへのアクセスのためにnHibernateをあきらめたとしても動作します(多分私は別のショットを与えるでしょう...) – Eilistraee