2010-11-10 3 views
1

У меня проблема с Fluent NHibernate, где автопилотирование не собирает entitites в моей DLL веб-проекта. Обычно я сохраняю все объекты в отдельной сборке, и это всегда срабатывало. Однако этот проект довольно мал, поэтому я стараюсь сохранить его в одном проекте. Однако, когда я звоню AutoMap.AssemblyOf<MyEntityType>(), сопоставлений не создается. Мне интересно, если это происходит потому, что объект живет в сборке веб-проектов, который загружается из папки временных файлов ASP.NET, а не в фактическую папку, где проект живет на диске. Это вопрос разрешения или что-то еще? Я не уверен, где начать отладку ...Fluent NHibernate automapping not working

Пример лицо:

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() 
      ); 

     // ... 

Я изменил положение Где искать для конкретного типа вместо пространство имен, но это тоже не сработало. объект сопоставления по-прежнему заканчивается пустым.

Кроме того, класс EntityBase представляет собой пустой класс, но для одного свойства Id, которое наследуется всеми объектами.

EDIT: Я переместил объекты на свою собственную сборку, и у меня все еще проблема, поэтому она не связана с расположением сборки веб-проекта. Я все еще довольно потерял это. :(

+0

Можете ли вы привести пример одного из ваших сущностей и кода, который вы используете для создания фабрики конфигурации/сеанса? –

+0

Я добавил пример кода – Chris

+0

Что произойдет, если вы добавите 'virtual' ко всем свойствам? NHibernate требует, чтобы все свойства были 'virtual'. –

ответ

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. Я создал [вопрос] (http://is.gd/gXTeT), поэтому он исправляется в будущей версии. –

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

+0

Является ли ваше приложение ASP.NET запущенным в средстве доверия или полного доверия? –

+0

Полный сервер доверия на локальном компьютере – Chris

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

Этот код был в состоянии экспортировать сопоставления успешно.

Edit:

Просто увидел свой ответ. Не знаю, почему установка IgnoreBase() устраняет проблему. Это должно только определить, как базовый класс должен быть сопоставлен для стратегии подкласса. Ну что ж.

+0

Да, я не думал, что это тоже необходимо. Не было сообщения об ошибке относительно самого сопоставления - только возможное сообщение «Нет persister for ...» при попытке сохранить объект, поэтому я все еще не уверен, в чем проблема. Все, что я знаю, игнорирует базу, которая явно исправила ее. – Chris

+0

Рад это услышать. Вы можете создать отдельный класс, который реализует 'DefaultAutomappingConfiguration' и передает его в метод' Configure() ', используя' m => m.AutoMappings.Add (AutoMap.Assemblies (новый CustomAutoMappingConfiguration(), typeof (Entity). Assembly) '. В более новых версиях FNH метод' AssemblyOf' устарел. Класс 'DefaultAutomappingConfiguration' имеет переопределения, которые позволяют вам действительно настраивать автоматические настройки и предпочтительнее. –

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 

Что дает? Кажется, конвенционный подход не подключен?

Смежные вопросы