在我的应用程序中,我需要与多个数据库通信。我在NHibernate中通过为每个数据库创建一个SessionFactory来处理它(我认为这是正确的事情)。所以我有两组模型(每个数据库一个)和两组Fluent NHibernate ClassMap<>
映射。两者都在同一个项目中(由命名空间分隔),我想保持这种方式。
创建SessionFactory时出现问题。据我所知,Fluent NHibernate基本上有两种添加映射的方法:
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<UserClassMap>())
.Mappings(m => m.FluentMappings.Add<UserClassMap>()
如果我使用第一个重载,那么我的会话工厂将获得两个数据库的所有映射。如果我使用第二个,我必须指定每个单独的ClassMap。我喜欢像FluentMappings.AddFromNamespace()
这样的东西。有没有办法做到这一点?
答案 0 :(得分:16)
很奇怪,FluentNHibernate支持这种类型的自动化过滤,但不支持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"));
答案 1 :(得分:10)
我最终写了一个扩展方法,为我做这个。基本上它使用反射来迭代我感兴趣的所有类型,并逐个添加它们。它基于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);
}
}
注意事项:
AddFromAssemblyAndNamespaceOf
,但这有点冗长。但它适用于我的目的。
答案 2 :(得分:0)
没有办法做到这一点。我建议将命名空间分成单独的项目。记住:
单独的命名空间,逻辑分离有意义的同一项目。 在物理分离有意义时,单独的命名空间,单独的项目。
在这种情况下,由于您无法在nhibernate映射中按名称空间分隔,因此物理分离是有意义的。但是,您可以使用使用.Where或ShouldMap配置的流畅自动机来解决这个问题。查找流畅的自动化程序,看看它是否可以帮助您达到目标。
答案 3 :(得分:0)
... AutoMap.AssemblyOf<Person>().Where(x => x.Namespace.EndsWith("Domain")) ...