2010-11-10 63 views
1

我有一個問題與流利NHibernate的地方automapping不拿起我的web項目DLL中的實體。通常我將所有實體存儲在一個單獨的程序集中,並且一直運行。然而,這個項目很小,所以我試圖把它全部保存在一個項目中。但是,當我撥打AutoMap.AssemblyOf<MyEntityType>()時,不會創建映射。我想知道這是否是因爲實體存在於從Temporary ASP.NET文件夾加載的Web項目程序集中,而不是項目駐留在磁盤上的實際文件夾。它是一個權限問題或什麼?我不知道從哪裏開始調試......流利NHibernate的自動映射不工作

例實體:

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; } 
    } 
}  

相關的自舉代碼:

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子句來尋找特定類型的,而不是命名空間,但也沒有工作。映射對象仍然是空的。

此外,EntityBase類是一個空的類,但對於所有實體繼承的一個屬性「Id」。

編輯:我將實體移到自己的程序集,仍然有問題,所以它沒有關係到web項目程序集的位置。這件事我還是很迷茫。 :(

+0

你可以舉一個你的實體和你用來創建配置/會話工廠的代碼的例子嗎? – 2010-11-10 20:30:56

+0

我添加了代碼示例 – Chris 2010-11-10 20:34:16

+0

如果向所有屬性添加「虛擬」,會發生什麼情況? NHibernate要求所有屬性都是「虛擬」的。 – 2010-11-10 20:38:15

回答

2

我發現問題:我從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() 
     ); 

    // ... 
+0

Fluent NHibernate以遞歸的方式遍歷類層次結構,以確保它獲得了需要映射的所有屬性。它需要查看'EntityBase',以防有後代需要的任何屬性;然而,這對我們/ FNH來說是一個疏忽,它也認爲它們可以被納入繼承層次中,即使它們不屬於where子句的標準。我創建了一個[issue](http://is.gd/gXTeT),以便在將來的版本中得到修復。 – 2010-11-12 10:44:11

0

試試這個,讓我知道會發生什麼。

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的沒有打擾到創建的映射

+0

沒有骰子。此外,單獨配置映射始終有效。沒有什麼能改變這一點出於某種原因,它只是沒有檢測到(或選擇映射)我的實體。 – Chris 2010-11-10 21:05:55

+0

您的ASP.NET應用程序是以中等信任度還是完全信任度運行? – 2010-11-10 21:07:15

+0

完全信任 - 本地機器上的開發服務器 – Chris 2010-11-10 21:09:58

0

我創建了一個新的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()修復這個問題。這應該只能確定如何爲子類策略映射基類。好吧。

+0

是的,我認爲它不應該被要求。沒有關於映射本身的錯誤信息 - 只有當試圖保存對象時最終出現「No persister for ...」消息 - 所以我仍然不確定問題是什麼。我所知道的是忽視基地明確固定它。 – Chris 2010-11-10 21:35:57

+0

很高興聽到這個消息。您可能希望創建一個單獨的類,該類使用'm => m.AutoMappings.Add(AutoMap.Assemblies(new CustomAutoMappingConfiguration(),typeof(Entity))實現'DefaultAutomappingConfiguration'並將其傳遞給'Configure()'方法。 Assembly)''在新版本的FNH中,'AssemblyOf'方法已被棄用,'DefaultAutomappingConfiguration'類覆蓋了你可以真正配置自動映射的輸入和輸出,並且是未來首選的方法。 – 2010-11-10 21:38:41

0

我發現域類需要位於與構建ISessionFactory的代碼不同的程序集中。一旦將域對象移動到單獨的程序集中,一切都可以正常工作。

出於好奇,我嘗試了Conventions.Add從上面的想法,它從來沒有工作。意思是,我可以帶域類像這樣:

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 

什麼給?看起來會議方式沒有接線?