2009-11-06 2 views
1

예제 프로그램을 성공적으로 끝내면 Fluent NHibernate와 함께 Real Work를 시작합니다. 프로젝트 클래스 인 heirarchy에서 Automapping을 사용하려고합니다.Fluent NHibernate로 <float>리스트 또는 float []를 어떻게 automap합니까?

과학적인 계측 응용 프로그램이며, 내가 매핑하는 클래스는 몇 가지 속성이 있습니다.

private float[] _rawY; 
    public virtual float[] RawY 
    { 
     get 
     { 
      return _rawY; 
     } 
     set 
     { 
      _rawY = value; 
     } 
    } 

이러한 배열은 최대 500 개의 값을 포함 할 수 있습니다.

오토 맵핑이 어레이에서 작동한다고는 예상하지 못했지만 어쨌든 시도해 보니 약간의 성공이 먼저있었습니다. 각 배열은 BLOB (SQLite 사용)으로 자동 매핑 되었기 때문에 가능한 솔루션처럼 보였습니다.

배열을 포함하는 개체에서 SaveOrUpdate를 호출하려고 할 때 첫 번째 문제가 발생했습니다. "float []에 대한 불만족" 예외가 있습니다.

내 생각에 모든 배열을 ILists로 변환하는 것이 었습니다.

public virtual IList<float> RawY { get; set; } 

하지만 지금 내가 얻을 : 자동 매핑은 복잡한 객체의 목록을 처리 할 수 ​​있기 때문에, 그것은 나에게 발생하지

NHibernate.MappingException: Association references unmapped class: System.Single 

은 기본 유형의 목록을 매핑 할 수 없습니다. 그러나 솔루션에 대한 인터넷 검색을 한 후에 이것이 맞는 것 같습니다. 어떤 사람들은 문제를 해결 한 것 같지만 샘플 코드 I 톱은 현재 가지고있는 것보다 NHibernate에 대한 지식이 더 필요합니다. - 은 그것을 이해하지 못했습니다.

질문 :

1. 어떻게 자동 매핑이 일을 할 수

?

2. 또한이 응용 프로그램에 대해 배열이나 목록을 사용하는 것이 더 좋습니까?

(필자는 목록을 선호하지만) 필요에 따라 앱을 수정할 수 있습니다.

편집 :

내가 Mapping Collection of Strings의 코드를 공부 한, 나는 테스트 코드 문자열의 IList의, 예를 설정하는 소스가 참조

public virtual IList<string> ListOfSimpleChildren { get; set; } 

[Test] 
public void CanSetAsElement() 
{ 
    new MappingTester<OneToManyTarget>() 
     .ForMapping(m => m.HasMany(x => x.ListOfSimpleChildren).Element("columnName")) 
     .Element("class/bag/element").Exists(); 
} 

은 그래서 이것은 순수한 자동 매핑을 사용 가능해야한다,하지만 난 수동으로 NHibernate에와 매핑 필요한 knowlege이없는 아마 때문에, 작업 제로 운이 점점 아무것도 했어.

내가 해킹해야 할 것 같아서 (누군가가 말할 수없는 한, 플로트 배열을 단일 문자열로 인코딩하거나, 단일 플로트가 포함 된 클래스를 만들어 목록에 집계해야 함) 나에게 그것을 올바르게하는 방법.

최종 편집

이이 응답을 공식화 도움이된다면 여기 내 CreateSessionFactory 방법,의 ...

private static ISessionFactory CreateSessionFactory() 
    { 
     ISessionFactory sessionFactory = null; 


     const string autoMapExportDir = "AutoMapExport"; 
     if(!Directory.Exists(autoMapExportDir)) 
      Directory.CreateDirectory(autoMapExportDir); 


     try 
     { 
      var autoPersistenceModel = 
       AutoMap.AssemblyOf<DlsAppOverlordExportRunData>() 
         .Where(t => t.Namespace == "DlsAppAutomapped") 
         .Conventions.Add(DefaultCascade.All()) 
       ; 


      sessionFactory = Fluently.Configure() 
       .Database(SQLiteConfiguration.Standard 
           .UsingFile(DbFile) 
           .ShowSql() 
         ) 
       .Mappings(m => m.AutoMappings.Add(autoPersistenceModel) 
              .ExportTo(autoMapExportDir) 
         ) 
       .ExposeConfiguration(BuildSchema) 
       .BuildSessionFactory() 
       ; 
     } 
     catch (Exception e) 
     { 
      Debug.WriteLine(e); 
     } 


     return sessionFactory; 
    } 

답변

2

Fluent NHibernate 팀이 내 질문을 게시 한이 문제를 해결했습니다.

이제 C# 값 유형 (문자열, 정수, 부동 소수점 등)의 IList를 자동 매핑 할 수 있습니다.

최신 버전의 FNH가 있는지 확인하십시오. 나는 최근 FNH 1.0에서 FNH 1.3로 업그레이드

편집.

이 버전은 또한 오토 배열합니다 -

등 [], [] int로 플로트,에 BLOB로 매핑하는 것 같다. 이 방법이 ILists보다 더 효율적이라고 가정하지만 확인을 위해 프로파일을 수행하지 않았습니다.

1

은 아마 많은 관계로 하나를 수행하고 목록을 다른 테이블을 만들 것입니다. ..

하지만 개체를 ​​다시 생각해 볼 필요가 있습니다. RawPoint로 작성할 수있는 RawX도 있습니까? 이렇게하면 3 개의 열 (ParentID, X, Y)이있는 표가 생성됩니다.

불연속성은 RDBMS에서 열을 매우 깔끔하게 처리하지 못하는 값으로 List를 매핑하려는 경우에 발생합니다. 테이블은 실제로 데이터 목록을 저장하는 데 사용하는 방법입니다.

이것은 NHibernate와 같은 ORM을 사용하는 요점입니다. 응용 프로그램에서 모든 쿼리 및 SQL 작성을 수동으로 수행 할 때 테이블을 추가하면 유지 관리 및 구현 비용이 많이 들었습니다. NHibernate의 경우 비용은 거의 0이므로 RDBMS의 강점을 활용하고 NHibernate를 추상화하여 추악하게 만듭니다.


난 당신이 오토 작업 할 경우 다음 어쩌면 컨벤션 재정의를 만들 수, 배열을 매핑하여 문제가 먼저 재정의 매핑을 시도하고 작동되는지 확인하십시오.

.Override<MyType>(map => 
{ 
    map.HasMany(x => x.RawY).AsList(); 
}) 

잘 작동하는지 확실하지 않은 경우이 구성 요소에 대해 구성된 nHibernate 테스트 설치를해야합니다.

+0

@Josh - 빠른 응답에 감사드립니다. 나는 당신이 어디로 가고 있는지보기는하지만, 실제로 실험을하기에 충분하지는 않습니다. 작은 코드 조각으로 응답자를 편집 할 수 있습니까? "나는 일대 다 많은 관계를 수행 할 것입니다 ..."에 대해 자세히 설명해 주시겠습니까? 또한 필자는 순수한 자동 매핑을 수행하고 있음에 유의하십시오. 명시 적 엔티티 매핑 클래스가 없습니다 (단, 문제를 해결할 수있는 유일한 방법 인 경우이를 추가 할 수 있다고 가정합니다). –

+0

IList 의 속성에 사용할 수있는 재정의 예제가 추가되었습니다. 시도해보십시오. – joshperry

+0

@Josh - 내 개체 모델에서 모든 IList properties에 대한 재정의를 시도했지만 여전히 "... 매핑되지 않은 클래스 : System.Single"예외가 발생합니다. –

0

여기 또는 실제로 작동 한 Fluent NHibernate 메일 링리스트에서 어떤 답도 얻지 못 했으므로 여기에 내가 한 일이 있습니다.

끔찍한 해킹 냄새가 있지만 작동합니다. (대형 데이터 세트까지 확장 할 수 있는지 여부는 아직 알 수 없음)

// Hack - need to embed simple types in a class before NHibernate 
// will map them 
public class MappableFloat 
{ 
    public virtual int Id { get; private set; } 
    public virtual float Value { get; set; } 
} 

내가 다음 예를 들어, 수레의 목록을 할 필요가 다른 클래스의 속성을 선언

첫째, 나는 클래스의 float 속성 (라는 값) 포장

public virtual IList<MappableFloat> RawYMappable { get; set; } 

NHibernate는 다중 외래 키 (예 :.

create table "MappableFloat" (
    Id integer, 
    Value NUMERIC, 
    DlsAppOverlordExportRunData_Id INTEGER, 
    DlsAppOverlordExportData_Id INTEGER, 
    primary key (Id) 
) 
1

결국 코드 목록의 끝 부분을 참조하십시오. 핵심 포인트는

  • DlsAppOverlordExportRunDataMap
  • CreateSessionFactory 또한

에서 UseOverridesFromAssemblyOf 조항의 추가라는 새로운 매핑 클래스, 그것은 그 (적어도 v를 밝혀 1.0.0.594) 거기에 아주 큰 잡았다 Automapping - 매핑 클래스 (예 : DlsAppOverlordExportRunDataMap)는 도메인 클래스와 같은 네임 스페이스에있을 수 없습니다 (예 :DlsAppOverlordExportRunData)!

그렇지 않으면, NHibernate에이 발생합니다 "NHibernate.MappingException : (을 XmlDocument) (2,4) : XML 유효성 검사 오류 : ..."를, 무엇을 어디서 실제 문제의 전혀 표시와 함께.

이것은 아마도 버그 일 수 있으며 이후 버전의 Fluent NHibernate에서 수정 될 수 있습니다.

namespace DlsAppAutomapped 
{ 
    public class DlsAppOverlordExportRunData 
    { 
     public virtual int Id { get; set; } 

     // Note: List<float> needs overrides in order to be mapped by NHibernate. 
     // See class DlsAppOverlordExportRunDataMap. 
     public virtual IList<float> RawY { get; set; } 
    } 
} 


namespace FrontEnd 
{ 
    // NEW - SET UP THE OVERRIDES 
    // Must be in different namespace from DlsAppOverlordExportRunData!!! 
    public class DlsAppOverlordExportRunDataMap : IAutoMappingOverride<DlsAppOverlordExportRunData> 
    { 
     public void Override(AutoMapping<DlsAppOverlordExportRunData> mapping) 
     { 
      // Creates table called "RawY", with primary key 
      // "DlsAppOverlordExportRunData_Id", and numeric column "Value" 
      mapping.HasMany(x => x.RawY) 
        .Element("Value"); 
     } 
    } 
} 

    private static ISessionFactory CreateSessionFactory() 
    { 
     ISessionFactory sessionFactory = null; 


     const string autoMapExportDir = "AutoMapExport"; 
     if(!Directory.Exists(autoMapExportDir)) 
      Directory.CreateDirectory(autoMapExportDir); 


     try 
     { 
      var autoPersistenceModel = 
       AutoMap.AssemblyOf<DlsAppOverlordExportRunData>() 
         .Where(t => t.Namespace == "DlsAppAutomapped") 

         // NEW - USE THE OVERRIDES  
         .UseOverridesFromAssemblyOf<DlsAppOverlordExportRunData>() 

         .Conventions.Add(DefaultCascade.All()) 
       ; 


      sessionFactory = Fluently.Configure() 
       .Database(SQLiteConfiguration.Standard 
           .UsingFile(DbFile) 
           .ShowSql() 
         ) 
       .Mappings(m => m.AutoMappings.Add(autoPersistenceModel) 
              .ExportTo(autoMapExportDir) 
         ) 
       .ExposeConfiguration(BuildSchema) 
       .BuildSessionFactory() 
       ; 
     } 
     catch (Exception e) 
     { 
      Debug.WriteLine(e); 
     } 


     return sessionFactory; 
    } 
관련 문제