Свободное автоматическое отображение NHibernate не работает - PullRequest
1 голос
/ 10 ноября 2010

У меня проблема с Fluent NHibernate, когда автоматическое сопоставление не получает права доступа в библиотеке DLL моего веб-проекта. Обычно я храню все объекты в отдельной сборке, и это всегда работало. Тем не менее, этот проект довольно маленький, поэтому я стараюсь держать все это в одном проекте. Однако когда я вызываю AutoMap.AssemblyOf<MyEntityType>(), сопоставления не создаются. Мне интересно, если это потому, что сущность живет в сборке веб-проекта, которая загружается из папки временных файлов 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, чтобы искать определенный тип вместо пространства имен, но это тоже не сработало. объект сопоставлений все еще остается пустым.

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

РЕДАКТИРОВАТЬ: Я переместил сущности в их собственную сборку, и у меня все еще остается проблема, поэтому она не связана с расположением сборки веб-проекта. Я все еще довольно потерян на этом. (

Ответы [ 4 ]

2 голосов
/ 11 ноября 2010

Я нашел проблему. Я наследовал от 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 голосов
/ 27 апреля 2011

Я обнаружил, что доменные классы должны быть в отдельной сборке, а не в коде, который создает ISessionFactory. Как только вы переместите ваши доменные объекты в отдельную сборку, все должно работать просто отлично.

Из любопытства я попробовал Конвенции. Добавьте идею сверху, и она никогда не работает. Это означает, что я могу взять класс домена, например:

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

С помощью процедуры AutoMapping, например ниже:

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

И измените мою процедуру AutoMapping так, чтобы она соответствовала ожидаемому имени нового свойства 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

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

0 голосов
/ 11 ноября 2010

Я создал новое 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 голосов
/ 11 ноября 2010

Попробуйте и дайте мне знать, что происходит:

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 не потрудился создать сопоставления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...