8

私のアプリケーションでは、複数のデータベースと通信する必要があります。私はこれをNHibernateでデータベースごとに1つのSessionFactoryを作成することで処理しています(これが正しいことだと思います)。したがって、2セットのモデル(データベースごとに1セット)と2セットのFluentNHibernateClassMap<>マッピングがあります。両方とも同じプロジェクト(名前空間で区切られている)にあり、そのままにしておきたいと思います。

SessionFactoryを作成するときに問題が発生します。私が見る限り、Fluent NHibernateには、マッピングを追加するための基本的に2つの方法があります。

    .Mappings(m => m.FluentMappings.AddFromAssemblyOf<UserClassMap>())
    .Mappings(m => m.FluentMappings.Add<UserClassMap>()

最初のオーバーロードを使用すると、セッションファクトリは両方のデータベースのすべてのマッピングを取得します。2番目を使用する場合は、個々のClassMapを指定する必要があります。のようなものが欲しいのですがFluentMappings.AddFromNamespace()。これを行う方法はありますか?

4

4 に答える 4

16

FluentNHibernateがこのタイプの自動マッピングのフィルタリングをサポートしているのは奇妙ですが、sはサポートしていませんClassMap。ただし、拡張メソッドの魔法を使って、この機能を自分で追加するのはそれほど難しいことではありません。これを試して:

public static FluentMappingsContainer AddFromAssemblyOf<T>(
    this FluentMappingsContainer mappings,
    Predicate<Type> where)
{
    if (where == null)
        return mappings.AddFromAssemblyOf<T>();

    var mappingClasses = typeof(T).Assembly.GetExportedTypes()
        .Where(x => (typeof(IMappingProvider).IsAssignableFrom(x)
                || typeof(IExternalComponentMappingProvider).IsAssignableFrom(x))
            && where(x));

    foreach (var type in mappingClasses)
    {
        mappings.Add(type);
    }

    return mappings;
}

...そして次のように使用します:

m.FluentMappings.AddFromAssemblyOf<UserClassMap>(t => t.Namespace.StartsWith("One.Of.The.Two.Namespaces"));
于 2011-06-01T20:17:07.553 に答える
10

私は私のためにこれを行う拡張メソッドを書くことになりました。基本的には、リフレクションを使用して、関心のあるすべてのタイプを反復処理し、それらを1つずつ追加します。これは、の実装に基づいていますAddFromAssemblyOf。使用法:

.Mappings(m => m.FluentMappings.AddFromNamespaceOf<UserClassMap>())

実装:

public static class FluentNHibernateExtensions
{
    public static FluentMappingsContainer AddFromNamespaceOf<T>(
        this FluentMappingsContainer fmc)
    {
        string ns = typeof(T).Namespace;
        IEnumerable<Type> types = typeof(T).Assembly.GetExportedTypes()
            .Where(t => t.Namespace == ns)
            .Where(x => IsMappingOf<IMappingProvider>(x) ||
                        IsMappingOf<IIndeterminateSubclassMappingProvider>(x) ||
                        IsMappingOf<IExternalComponentMappingProvider>(x) ||
                        IsMappingOf<IFilterDefinition>(x));

        foreach(Type t in types) {
            fmc.Add(t);
        }

        return fmc;
    }

    /// <summary>
    /// Private helper method cribbed from FNH source (PersistenModel.cs:151)
    /// </summary>
    private static bool IsMappingOf<T>(Type type)
    {
        return !type.IsGenericType && typeof(T).IsAssignableFrom(type);
    }
}

警告:

  • 名前は1つのアセンブリのみを検索するため、少し誤解を招く可能性があります。おそらく呼ばれるべきですがAddFromAssemblyAndNamespaceOf、それは少し冗長です。
  • 完全に将来にわたって利用できるわけではありません。FNHの将来のバージョンで、マッピング可能なインターフェイスの一部が追加または削除された場合、それらは含まれません。

しかし、それは私の目的のために機能します。

于 2011-06-01T20:19:55.613 に答える
0
... AutoMap.AssemblyOf<Person>().Where(x => x.Namespace.EndsWith("Domain")) ...
于 2011-06-01T19:51:33.950 に答える
0

これを行う方法はありません。名前空間を別々のプロジェクトに分割することをお勧めします。覚えて:

名前空間を分離し、論理的な分離が理にかなっている場合は同じプロジェクト。名前空間を分離し、物理的な分離が理にかなっている場合はプロジェクトを分離します。

この場合、nhibernateマッピングでは名前空間で分離できないため、物理的な分離は理にかなっています。ただし、.WhereまたはShouldMap構成を使用する流暢な自動マップを使用すると、これを回避できます。流暢なオートマップを調べて、それがあなたが望む場所に到達できるかどうかを確認してください。

于 2011-06-01T19:47:14.870 に答える