2011-08-05 94 views
0

我需要使用Fluent-nHibernate的組合主鍵(Azure表,主鍵是(PartitionKey,RowKey),我想映射他們與相應的屬性在實體(或組件屬性,如果更容易)複合主鍵聲明通過公約爲流利nHibernate

我的表看起來像:

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

與實體

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

    [...] 
} 

我當前的projet使用定製的nHibernate驅動程序來定位AzureTable。

我設法使它與ClassMap或XML映射一起工作。所以我相信司機在工作。此外,azure表HTTP請求使用classmaps或XML聲明是正確的。

但是我真的需要約定,所以這不是一個可以接受的解決方案。

最後,即使數據存儲區使用(PartitionKey,RowKey),也總是有選項將RowKey映射爲PK。它也可以工作,但它並不真正令人滿意,因爲它引入了一個處理nHibernate和底層數據存儲區不匹配的unicity。

UPDATE:

我試圖建立一個自定義IIdentityConvention。 IIdentityInstance.Column()方法僅考慮第一次調用。 但是,如果我使用反射將兩列添加到基礎映射字段,則配置生成將失敗,並顯示XML驗證異常(屬性'class'required)

回答

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

謝謝!它的工作,即使我最終放棄了nHibernate的Azure表訪問(也許我會再給它一次...) – Eilistraee