首页 文章

如何在Fluent NHibernate中通过命名空间添加映射

提问于
浏览
8

在我的应用程序中,我需要与多个数据库进行通信 . 我在NHibernate中通过为每个数据库创建一个SessionFactory来处理它(我认为这是正确的事情) . 所以我有两套模型(每个数据库一个)和两组Fluent NHibernate ClassMap<> 映射 . 两者都在同一个项目中(由命名空间分隔),我想保持这种方式 .

创建SessionFactory时出现问题 . 据我所知,Fluent NHibernate基本上有两种添加映射的方法:

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

如果我使用第一个重载,那么我的会话工厂将获得两个数据库的所有映射 . 如果我使用第二个,我必须指定每个单独的ClassMap . 我喜欢像 FluentMappings.AddFromNamespace() 这样的东西 . 有没有办法做到这一点?

4 回答

  • 10

    奇怪的是,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"));
    
  • 16

    我结束了写一个扩展方法,为我做这个 . 基本上它使用反射来迭代我感兴趣的所有类型,并逐个添加它们 . 它基于 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 ,但这有点冗长 .

    • 这不完全是面向未来的 . 如果FNH的未来版本添加或删除某些可映射接口,则不会包含它们 .

    但它适用于我的目的 .

  • 0
    ... AutoMap.AssemblyOf<Person>().Where(x => x.Namespace.EndsWith("Domain")) ...
    
  • 0

    没有办法做到这一点 . 我建议将命名空间分成单独的项目 . 记得:

    逻辑分离是有意义的,单独的命名空间,相同的项目 . 在物理分离有意义时,单独的命名空间,单独的项目 .

    在这种情况下,由于您无法在nhibernate映射中按名称空间分隔,因此物理分离是有意义的 . 但是,您可以使用使用.Where或ShouldMap配置的流畅自动机来解决这个问题 . 查找流畅的自动化程序,看看是否可以让你达到你想要的目标 .

相关问题