2011-08-05 3 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 드라이버를 사용합니다.

클래스 맵 또는 XML 매핑을 사용할 수 있도록 관리했습니다. 그러므로 나는 운전자가 일하고 있다고 확신한다. 또한, azure table HTTP 요청은 클래스 맵이나 XML 선언을 사용하여 정확합니다.

그러나 나는 정말 관습이 필요합니다. 그래서 이것은 받아 들일만한 해결책이 아닙니다.

마지막으로 Datastore가 (PartitionKey, RowKey)를 사용하더라도 RowKey 만 PK로 매핑하는 옵션이 항상 있습니다. 그것도 작동하지만 nHibernate와 기본 데이터 저장소 사이의 단일성 처리 불일치를 소개하므로 실제로 만족스럽지 않습니다.

업데이트 :

나는 사용자 정의 IIdentityConvention을 구축했습니다. IIdentityInstance.Column() 메서드는 첫 번째 호출 만 고려합니다. 그러나 리플렉션을 사용하여 기본 매핑 필드에 두 열을 추가하면 XML 유효성 검사 예외 (속성 '클래스'필요)와 함께 구성 빌드가 실패합니다. ('class'속성이 필요합니다.)

답변

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