AutoMapping を使用した Fluent NHibernate DuplicateMappingException
-
18-09-2019 - |
質問
まとめ:
Fluent NHibernate Automapper を使用して、同じ名前で異なる名前空間の 2 つのクラスを保存したいと考えています
コンテクスト
テストのためにさまざまなオブジェクトをデータベースにインポートする必要があると書いています。最終的には適切なモデルへのマッパーを作成します。
私は code gen と Fluent NHibernate を使用して、これらの DTO を取得し、データベースに直接ダンプしてきました。
例外は次のように述べています(auto-import="false"を使用してみてください)
コード
public class ClassConvention : IClassConvention
{
public void Apply(IClassInstance instance)
{
instance.Table(instance.EntityType.Namespace.Replace(".", "_"));
}
}
namespace Sample.Models.Test1
{
public class Test
{
public virtual int Id { get; set; }
public virtual string Something { get; set; }
}
}
namespace Sample.Models.Test2
{
public class Test
{
public virtual int Id { get; set; }
public virtual string SomethingElse { get; set; }
}
}
そして、これが実際のアプリのコードです
var model = AutoMap.AssemblyOf<Service1>()
.Where(t => t.Namespace.StartsWith("Sample.Models"))
.Conventions.AddFromAssemblyOf<Service1>();
var cfg = Fluently.Configure()
.Database(
MySQLConfiguration.Standard.ConnectionString(
c => c.Is("database=test;server=localhost;user id=root;Password=;")))
.Mappings(m => m.AutoMappings.Add(model))
.BuildConfiguration();
new SchemaExport(cfg).Execute(false, true, false);
ありがとうございます。助けていただければ幸いです
アップデート Fluent Nhibernate RC1 を使用する
解決
Fluent-nhibernate フォーラムからのソリューション ジェームズ・グレゴリー著
ちゃんと見てみた 今夜はこれ。基本的には、 AutoImportは例外を詰め込みます 前述の;NHibernateが与えられた場合 最初のマッピングでは、 エンティティは完全なアセンブリで名前が付けられます 修飾名を作成し、インポートを作成します 短い名前(役に立ちます!)、 そして、2番目のものを追加すると、 次に、このインポートが 今、競合するつもりです。だから解決策 自動インポートをオフにすることです。残念ながら、私たちにはその方法がありません RCでそれをやれ...私はちょうど コミットした修正は、 これを 大会。したがって、最新の バイナリまたはソースの場合は、 をクリックして、 これを行うには、添付されたプロジェクト:
.Conventions.Setup(x => {
x.AddFromAssemblyOf<Program>();
x.Add(AutoImport.Never()); });
これにより、アセンブリで定義したすべての規則が追加され、ヘルパーコンベンションの1つを使用して自動インポートをオフにします。
他のヒント
(AutoMappings とは対照的に) FluentMappings の Conventions を使用してこれを機能させることはできませんでした。ただし、以下は私にとっては機能しますが、必要に応じて各 ClassMap に追加する必要があります。
public class AMap : ClassMap<A>
{
public AMap()
{
HibernateMapping.Not.AutoImport();
Map(x => x.Item, "item");
...
}
}
私はこれに本当に問題を抱えており、上記の例またはその変形例は役に立ちません。
var cfg = new NotifyFluentNhibernateConfiguration();
return Fluently.Configure()
.Database(
FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2005
.ConnectionString("Server=10.2.65.227\\SOSDBSERVER;Database=NotifyTest;User ID=NHibernateTester;Password=test;Trusted_Connection=False;")
)
.Mappings(m => {
m.AutoMappings
.Add(AutoMap.AssemblyOf<SubscriptionManagerRP>(cfg));
m.FluentMappings.Conventions.Setup(x =>
{
x.AddFromAssemblyOf<Program>();
x.Add(AutoImport.Never());
});
} )
.BuildSessionFactory();
プログラムのリファレンスが見つかりません。
また、絶望的な設定に別の XML ファイルを置いて、fluent nhibernate の auto-import = false へのマッピングを試みましたが、成功しませんでした。
これを行う方法について、もう少し広範な例を教えていただけますか?
追記、つい数週間前に最新のトランクを入手しました。
編集、すべての重複を削除することでこれを解決しました。
私も同じ問題を抱えていました。私は次のように解決しました:
Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008
.ConnectionString(...)
.AdoNetBatchSize(500))
.Mappings(m => m.FluentMappings
.Conventions.Setup(x => x.Add(AutoImport.Never()))
.AddFromAssembly(...)
.AddFromAssembly(...)
.AddFromAssembly(...)
.AddFromAssembly(...))
;
インポートされた部分は次のとおりです。 .Conventions.Setup(x => x.Add(AutoImport.Never()))
. 。この構成ではすべてが正常に動作しているようです。
使用 バインドマッピング前 イベントを使用して、.HBM XML ファイルのオブジェクト表現にアクセスします。
このイベントを使用すると、NHibernate セッション ファクトリが作成される前に実行時にプロパティを変更できます。これにより、FluentNHibernate と同等の規約も不要になります。残念ながら、この本当に素晴らしい機能に関する公式ドキュメントは現在ありません。
ここでは、重複マッピングの問題に対するグローバルな解決策を示します (すべての HQL クエリでは、クラス名だけではなく完全修飾型名を使用する必要があることに注意してください)。
var configuration = new NHibernate.Cfg.Configuration();
configuration.BeforeBindMapping += (sender, args) => args.Mapping.autoimport = false;
AutoImport.Never() という規則をどこに追加するかを検討する必要がありました。永続マッピングをさまざまなプロジェクトに分けています。各アプリケーションのモデルもさまざまなプロジェクトにあります。Fluent NHibernate と自動マッピングで使用します。
ドメインやマッピングを実際に組み合わせる必要がある場合があります。これは、すべてのドメインにアクセスする必要がある場合です。上記の例のように、使用される POCO クラスは同じ名前で異なる名前空間を持つ場合があります。
すべてのマッピングを結合すると次のようになります。
internal static class NHIbernateUtility
{
public static ISessionFactory CreateSessionFactory(string connectionString)
{
return Fluently.Configure()
.Database(
MsSqlConfiguration
.MsSql2008
.ConnectionString(connectionString))
.Mappings(m => m.AutoMappings
.Add(ProjectA.NHibernate.PersistenceMapper.CreatePersistenceModel()))
.Mappings(m => m.AutoMappings
.Add(ProjectB.NHibernate.PersistenceMapper.CreatePersistenceModel()))
.Mappings(m => m.AutoMappings
.Add(ProjectC.NHibernate.PersistenceMapper.CreatePersistenceModel())).BuildSessionFactory();
}
}
そして永続性マッパーの 1 つ:
public static class PersistenceMapper
{
public static AutoPersistenceModel CreatePersistenceModel()
{
return
AutoMap.AssemblyOf<Credential>(new AutoMapConfiguration())
.IgnoreBase<BaseEntity>()
.Conventions.Add(AutoImport.Never())
.Conventions.Add<TableNameConvention>()
.Conventions.Add<StandardForeignKeyConvention>()
.Conventions.Add<CascadeAllConvention>()
.Conventions.Add<StandardManyToManyTableNameConvention>()
.Conventions.Add<PropertyConvention>();
}
}
永続化マッパーは、POCO 名前空間ごとに非常に似ており、オーバーライドを持つものもあります。各永続化マッパーに .Conventions.Add(AutoImport.Never()) を追加する必要がありましたが、それは魅力的に機能します。
他の誰かがこの方法を行っている場合は、これを共有したかっただけです。