1

NHibernate 현지화에 대해 few good articles을 읽었지만 아무 것도이 시나리오에 잘 맞지 않는 것 같습니다. Google DB는 현지화 된 정보를 다음 패턴으로 저장합니다.NHibernate : 사용자 문화를 기반으로 컬럼을 바꿔서 현지화

TABLE NAME: PRODUCT 
COLUMNS: 
ID 
PRODUCT_CODE 
PRODUCT_NAME 
DESCRIPTION1 
DESCRIPTION2 
DESCRIPTION3 

DESCRIPTION1, DESCRIPTION2 및 DESCRIPTION3 필드는 제품의 현지화 된 설명을 포함합니다. 항상 정확히 3 개의 지역화 된 문자열이 있으며 숫자는 항상 동일한 문화권을 참조합니다 (예 : 3은 영어 임). 다른 테이블에는 NAME1, NAME2 및 NAME3과 같은 열이 있습니다.

(Fluent) NHibernate를 사용하여 모델 클래스에 "설명"이라는 하나의 속성 만 포함하고 올바른 필드에서 얻은 값을 포함하도록 이러한 열에 매핑하고 싶습니다. 현재 스레드의 문화권. NHibernate에 대한 확장 점이 여러 개 있지만 가장 좋은 점은 무엇입니까?

문자열 속성을 올바른 열로 동적으로 매핑 하시겠습니까?

내 꿈의 세계에서 나는 Description-field를 String으로 가질 것입니다.

public class Product 
{ 
    /* ... */ 

    public virtual string Description { get; set; } 
} 

그리고 ClassMap에 어떻게 든 올바른 열 이름은 런타임에 평가되는 유창함 NHibernate에로 말할 것 :

쿼리가이 매핑을 실행
public class ProductMap : ClassMap<Product> 
{ 
    public ProductMap() 
    { 
     /* ... */ 

     MapAsLocalized(x => x.Description); 
    } 
} 

, 내 코드를 자동 싶습니다 스레드의 culture를 확인하고이를 기반으로 올바른 열을 선택합니다. 예를 들어 culture가 en-US 인 경우 쿼리는 DESCRIPTION3 열에서 Description 속성으로 값을 가져옵니다.

맞춤 IUSERTYPE?

하지만 날이 같은 제품 수준의 정의 할 수 있도록 해주는 사용자 정의 LocalizedString 수준에 정착 할 수이 가능하지 않은 경우 :

public class Product 
{ 
    /* ... */ 

    public virtual LocalizedString Description { get; set; } 
} 

을 그리고 다음과 같은 예를 들어 지역화 된 값을 얻을 :

다음 LocalizedString-예에서

 // Product prod; 
     // Get product from db 

     Console.WriteLine(prod.Description.Value); 

는 생각은 dev에 여전히 모든 설명 컬럼에 매핑을 만들 필요없이지도를 만들 수 있다는 것입니다

public class ProductMap : ClassMap<Product> 
{ 
    public ProductMap() 
    { 
     /* ... */ 

     Map(x => x.Description); 
    } 
} 

그리고이 맵으로 쿼리를 실행하면 DESCRIPTION1, DESCRIPTION2 및 DESCRIPTION3의 값을 LocalizedString (내부적으로 일종의 컬렉션) 내에 반환합니다.

솔루션 1 또는 솔루션 2 구현 방법에 대한 권장 사항은 무엇입니까? 아니면 둘 다?

+0

유일한 추천 (쓸모없는) 내가 줄 수있는 DB 스키마를 수정하는 것입니다 : 당신이

및 사용을 원하는 경우 나는 구현을 보낼 수 있습니다. 현재 디자인에 다른 언어를 어떻게 추가 하시겠습니까? –

+0

불행히도 우리 데이터베이스는 거의 20 년 전부터 거슬러 올라갑니다. –

+0

투영법을 과도하게 사용하거나 전혀 사용하지 않습니까? 이것은 솔루션에 영향을 미칩니다. –

답변

2

당신은 몇 가지 IUserType 방법을 구현

public class LocalizationUserType : ImmutableUserType 
{ 
    public override object NullSafeGet(IDataReader rs, string[] names, object owner) 
    { 
     switch(Languageprovider.GetLanguage()) 
     { 
      case language1: 
        return NHibernateUtil.String.NullSafeGet(cmd, value, index); 
      case language2: 
        return NHibernateUtil.String.NullSafeGet(cmd, value, index + 1); 
      ... 
     } 
     return null; 
    } 

    public override void NullSafeSet(IDbCommand cmd, object value, int index) 
    { 
     switch(Languageprovider.GetLanguage()) 
     { 
      case language1: 
        NHibernateUtil.String.NullSafeSet(cmd, value, index); 
        break; 
      case language2: 
        NHibernateUtil.String.NullSafeSet(cmd, value, index + 1); 
        break; 
      ... 
     } 
    } 

    public override Type ReturnedType 
    { 
     get { return typeof(String); } 
    } 

    public override SqlType[] SqlTypes 
    { 
     get { return new[] 
     { 
      SqlTypeFactory.GetString(1000), 
      SqlTypeFactory.GetString(1000), 
      SqlTypeFactory.GetString(1000), 
     }; } 
    } 
} 

ImmutableUserType가없는 baseclass하는 유저 유형으로 갈 수 있습니다.

public class ProductMap : ClassMap<Product> 
{ 
    ProductMap 
    { 
     ... 
     Map(p => p.Name) 
      .Columns.Add("name1", "name2", "name3") 
      .CustomType<LocalizationUserType>(); 

     ... 
     Map(p => p.Description) 
      .Columns.Add("desc1", "desc2", "desc3") 
      .CustomType<LocalizationUserType>(); 
0

NHibernate는 런타임에 매핑을 수정할 수있는 기능을 제공하지만. NHibernate가 질의를하고 싶을 때마다 세션 팩토리를 다시 빌드하는 것은 성능을 심각하게 저해 할 수 있습니다. 두 번째 생각을 사용하는 것이 좋습니다. 사용자 정의 IUserType조차 필요하지 않습니다. 이를 구성 요소로 맵핑 할 수 있습니다.

Component(x => x.Description, c => 
    { 
      c.Map(d => d.Description1); 
      ... 
    }); 

또는 당신은 당신의 제품의 클래스의 백업 필드에 그 설명의 각을지도하고 런타임에 해당 필드를 선택하는 공공 설명 속성을 제공 할 수 있습니다.

관련 문제