代码之家  ›  专栏  ›  技术社区  ›  Chris

流畅的NHibernate自动映射不起作用

  •  1
  • Chris  · 技术社区  · 14 年前

    我对Fluent NHibernate有一个问题,自动映射没有在我的web项目DLL中获取实体。通常,我将所有实体存储在一个单独的程序集中,这一直有效。然而,这个项目是相当小的,所以我试图保持在一个项目所有。但是,当我打电话给 AutoMap.AssemblyOf<MyEntityType>() ,未创建映射。我想知道这是否是因为实体位于web项目程序集中,该程序集从临时的ASP.NET文件文件夹加载,而不是项目位于磁盘上的实际文件夹中。是权限问题还是什么?我不知道从哪里开始调试。。。

    示例实体:

    namespace MyProject.Entities 
    {
        public class Letter : EntityBase
        {
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public string Company { get; set; }
            public string Address1 { get; set; }
            public string Address2 { get; set; }
            public string City { get; set; }
            public string State { get; set; }
            public string Zip { get; set; }
            public string Country { get; set; }
            public string Interest { get; set; }
            public string Section1 { get; set; }
            public string Section2 { get; set; }
            public string Section3 { get; set; }
            public string LetterText { get; set; }
            public int StepNumber { get; set; }
        }
    }    
    

    相关boostrap代码:

       private static ISessionFactory GetSessionFactory()
        {
            var database = MsSqlConfiguration.MsSql2005
                .ConnectionString(Configuration.ConnectionString)
                .DefaultSchema(DEFAULT_SCHEMA)
                .AdoNetBatchSize(BATCH_SIZE);
    
            var mappings = AutoMap.AssemblyOf<Letter>()
                .Where(x => x.GetType() == typeof(Letter))
                .Conventions.Add
                (
                    ConventionBuilder.Id.Always(x =>
                        x.GeneratedBy.HiLo(HILO_TABLE, HILO_COLUMN, HILO_MAX_LO)),
                    ConventionBuilder.HasMany.Always(x => x.Cascade.AllDeleteOrphan()),
                    Table.Is(o => Inflector.Pluralize(o.EntityType.Name)),
                    PrimaryKey.Name.Is(o => "Id"),
                    ForeignKey.EndsWith("Id"),
                    DefaultLazy.Never(),
                    DefaultCascade.All()
                );
    
            // ...
    

    我更改了Where子句以查找特定类型而不是名称空间,但这也不起作用。mappings对象最终还是空的。

    此外,EntityBase类是一个空类,但对于一个由所有实体继承的属性“Id”。

    编辑: 我将实体移到了它们自己的程序集中,但仍有问题,因此它与web项目程序集的位置无关。我还是很迷恋这个。:(

    4 回复  |  直到 14 年前
        1
  •  2
  •   Nathan Koop    14 年前

    我发现了问题。我是从EntityBase继承的,但没有IgnoreBase调用。我假设由于EntityBase不在命名空间中,所以我不需要它来进行映射,但显然,如果不显式忽略基类,即使它是另一个命名空间,映射也将失败。

    新的引导代码如下:

    private static ISessionFactory GetSessionFactory()
    {
        var database = MsSqlConfiguration.MsSql2005
            .ConnectionString(Configuration.ConnectionString)
            .DefaultSchema(DEFAULT_SCHEMA)
            .AdoNetBatchSize(BATCH_SIZE);
    
        var mappings = AutoMap.AssemblyOf<Letter>()
            .Where(x => x.GetType() == typeof(Letter))
            .IgnoreBase<EntityBase>()
            .Conventions.Add
            (
                ConventionBuilder.Id.Always(x =>
                    x.GeneratedBy.HiLo(HILO_TABLE, HILO_COLUMN, HILO_MAX_LO)),
                ConventionBuilder.HasMany.Always(x => x.Cascade.AllDeleteOrphan()),
                Table.Is(o => Inflector.Pluralize(o.EntityType.Name)),
                PrimaryKey.Name.Is(o => "Id"),
                ForeignKey.EndsWith("Id"),
                DefaultLazy.Never(),
                DefaultCascade.All()
            );
    
        // ...
    
        2
  •  0
  •   Daniel T.    14 年前

    试试这个让我知道会发生什么:

    var config = Fluently.Configure()
        .Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf<Letter>()
            .Where(n => n.Name == "Letter"))
            .ExportTo(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop) + "/mappings"))
        .BuildConfiguration();
    
    var factory = config.BuildSessionFactory();
    

    我完全不知道你是不是在打电话 BuildConfiguration() ,因此NHibernate不必费心创建映射。

        3
  •  0
  •   Daniel T.    14 年前

    我创造了一个新的 ASP.NET MVC 应用程序并添加了这两个类和此配置:

    public abstract class Entity
    {
        public int Id { get; set; }
    }
    
    public class Letter
    {
        public string Name { get; set; }
    }
    
    // this is in Global.asax
    protected void Application_Start()
    {
        Fluently.Configure()
            .Database(SQLiteConfiguration.Standard.InMemory())
            .Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf<Entity>()
                .Where(t => t.IsSubclassOf(typeof (Entity))))
                .ExportTo(*the desktop*))
            .BuildConfiguration();
    }
    

    此代码能够成功导出映射。

    编辑:

    刚刚看到你的答案。不知道为什么 IgnoreBase() 解决了这个问题。它应该只决定如何为子类策略映射基类。哦,好吧。

        4
  •  0
  •   brady gaster    14 年前

    我发现域类需要位于单独的程序集中,而不是构建ISessionFactory的代码中。一旦将域对象移动到单独的程序集中,一切都应该正常工作。

    出于好奇,我尝试了惯例。从上面加上想法,它就永远不会起作用。意思是,我可以使用这样的域类:

    public class Person
        {
            public virtual int Id { get; private set; }
            public virtual string FirstName { get; set; }
            public virtual string LastName { get; set; }
        }
    

    自动映射程序如下:

    public NHibernate.ISessionFactory Create()
            {
                var persistenceModel =
                    AutoMap
                        .AssemblyOf<Person>();
    
                var ret =
                    Fluently
                        .Configure()
                        .Database(MsSqlCeConfiguration.Standard.ShowSql().FormatSql().ConnectionString(ex => ex.FromConnectionStringWithKey("PersonSqlCe")))
                        .Mappings(x => x.AutoMappings.Add(persistenceModel))
                        .ExposeConfiguration(config =>
                            {
                                new SchemaExport(config).Create(true, true);
    
                                // DOC: workaround for identity column failures in SQLCE
                                config.SetProperty("connection.release_mode", "on_close");
                            })
                        .BuildSessionFactory();
    
                return ret;
            }
    

    一切都很好。但是,当我将域类更改为如下所示时:

    public class Person
        {
            public virtual int BAD { get; private set; }
            public virtual string FirstName { get; set; }
            public virtual string LastName { get; set; }
        }
    

    并更改我的自动映射例程以符合新的PrimaryKey属性名称期望,如下面的代码:

    public NHibernate.ISessionFactory Create()
            {
                var persistenceModel =
                    AutoMap
                        .AssemblyOf<Person>();
    
                persistenceModel.Conventions.Add(PrimaryKey.Name.Is(x => "BAD"));
    
                var ret =
                    Fluently
                        .Configure()
                        .Database(MsSqlCeConfiguration.Standard.ShowSql().FormatSql().ConnectionString(ex => ex.FromConnectionStringWithKey("PersonSqlCe")))
                        .Mappings(x => x.AutoMappings.Add(persistenceModel))
                        .ExposeConfiguration(config =>
                            {
                                new SchemaExport(config).Create(true, true);
    
                                // DOC: workaround for identity column failures in SQLCE
                                config.SetProperty("connection.release_mode", "on_close");
                            })
                        .BuildSessionFactory();
    
                return ret;
            }
    

    ... 我有如下错误:

      ----> FluentNHibernate.Visitors.ValidationException : The entity 'Person' doesn't have an Id mapped. Use the Id method to map your identity property. For example: Id(x => x.Id).
        at FluentNHibernate.Cfg.FluentConfiguration.BuildSessionFactory()
        SampleImplementation.cs(28,0): at NHQS.Tests.PersonSampleSessionFactoryCreator.Create()
        SessionFactoryTests.cs(16,0): at
    

    什么给你?似乎会议的方法没有接通?