1

サンプル プログラムが正常に動作するようになったので、Fluent NHibernate を使用して実際の作業を開始します。プロジェクトのクラス階層で Automapping を使用しようとしています。

これは科学計測アプリケーションであり、マッピングしているクラスには、float の配列であるいくつかのプロパティがあります。

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

これらの配列には、最大 500 個の値を含めることができます。

自動マッピングが配列で機能するとは思っていませんでしたが、とにかく試してみて、最初はある程度成功しました。各配列は (SQLite を使用して) BLOB に自動マップされ、実行可能なソリューションのように見えました。

最初の問題は、配列を含むオブジェクトで SaveOrUpdate を呼び出そうとしたときに発生しました。「float [] の永続化がありません」という例外が発生しました。

だから私の次の考えは、すべての配列を IList に変換することでした。

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

しかし、今私は得る:

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

Automapping は複雑なオブジェクトのリストを処理できるため、基本型のリストをマップできないとは思いもしませんでした。しかし、解決策のためにいくつかのグーグルを行った後、これは事実のようです。一部の人々は問題を解決したようですが、私が見たサンプル コードは、私が今持っているよりも多くの NHibernate の知識を必要とします - 私はそれを理解していませんでした。

質問:

1. Automapping でこれを機能させるにはどうすればよいですか?

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(); 
} 

したがって、これは純粋な Automapping を使用して可能であるに違いありませんが、おそらく NHibernate で手動でマッピングするための必要な知識がないため、何も機能させることができませんでした。

誰かが私に方法を教えてくれない限り、これをハックする必要があると考え始めています (float の配列を単一の文字列としてエンコードするか、単一の float を含むクラスを作成し、それをリストに集約します)。それを適切に。

編集を終了

これが私の 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; 
    } 
4

4 に答える 4

2

私が質問を投稿して以来、FluentNHibernateチームはこの問題を修正しました。

C#値タイプ(文字列、int、floatなど)のIListを自動マップできるようになりました。

FNHの最新バージョンがあることを確認してください。

編集

最近、FNH1.0からFNH1.3にアップグレードしました。

このバージョンでは、配列(float []、int []など)も自動マップされます。

それらをBLOBとしてマップしているようです。これはIListsよりも効率的だと思いますが、確認のためのプロファイリングは行っていません。

于 2010-03-25T20:17:39.240 に答える
2

私はおそらく一対多の関係を作り、リストを別のテーブルにします...

しかし、オブジェクトを再考する必要があるかもしれません.RawPointに構成できるRawXもありますか? これにより、3 つの列 (ParentID、X、Y) を持つテーブルが作成されます。

不連続性は、List を、RDBMS では列に適切に配置されない値にマップしたい場合に発生します。テーブルは実際には、データのリストを格納するために使用する方法です。

これが、NHibernate のような ORM を使用するポイントです。アプリケーションですべてのクエリと SQL 構成を手作業で行う場合、テーブルを追加すると、メンテナンスと実装に多大なコストがかかりました。NHibernate を使用すると、コストはほぼゼロになるため、RDBMS の長所を活用して、NHibernate に醜さを抽象化させてください。


配列のマッピングに関する問題を確認しました。最初にオーバーライド マッピングで試してみて、それが機能するかどうかを確認してください。次に、自動マップを機能させたい場合は、規則のオーバーライドを作成できます。

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

それが機能するかどうかわからないので、nHibernate のテスト セットアップをこのために構成する必要があります。

于 2009-11-06T22:14:37.143 に答える
1

最終的にはオーバーライドが機能するようになりました。コードリストの最後を参照してください。重要なポイントは次のとおりです。

  • DlsAppOverlordExportRunDataMapと呼ばれる新しいマッピングクラス
  • CreateSessionFactoryにUseOverridesFromAssemblyOf句を追加

また、(少なくともv。1.0.0.594では)自動マッピングには非常に大きな落とし穴があります。マッピングクラス(DlsAppOverlordExportRunDataMapなど)をドメインクラス(DlsAppOverlordExportRunDataなど)と同じ名前空間に含めることはできません。

それ以外の場合、NHibernateは「NHibernate.MappingException:(XmlDocument)(2,4):XML検証エラー:...」をスローしますが、実際の問題が何であるか、どこにあるかはまったく示されません。

これはおそらくバグであり、FluentNHibernateの新しいバージョンで修正される可能性があります。

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; 
    } 
于 2009-11-25T22:07:25.163 に答える
0

ここまたは Fluent NHibernate メーリング リストで実際に機能する回答が得られなかったので、ここで私がしたことを示します。

恐ろしいハックのようなにおいがしますが、うまくいきます。(大規模なデータ セットにスケールアップするかどうかはまだわかりません)。

まず、float プロパティ (Value と呼ばれる) をクラスにラップしました。

// 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; }
}

次に、フロートのリストである必要がある他のクラスでプロパティを宣言します。

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

NHibernate は、複数の外部キーを持つ単一のデータベース テーブルを作成します。

create table "MappableFloat" (
    Id  integer,
   Value NUMERIC,
   DlsAppOverlordExportRunData_Id INTEGER,
   DlsAppOverlordExportData_Id INTEGER,
   primary key (Id)
)
于 2009-11-13T22:16:57.770 に答える