Как настроить несколько сопоставлений с помощью FluentHibernate? - PullRequest
1 голос
/ 25 марта 2010

Первый раз покачивайте его с помощью NHibernate / Fluent, поэтому заранее извиняюсь, если это наивный вопрос. У меня есть набор моделей, которые я хочу отобразить. Когда я создаю свою фабрику сессий, я пытаюсь сделать все отображения одновременно. Я не использую автоматическое отображение (хотя могу, если то, что я пытаюсь сделать, окажется более болезненным, чем должно быть). Проблема, с которой я сталкиваюсь, заключается в том, что кажется, что берется только верхняя карта. Учитывая приведенный ниже фрагмент кода и выполнение модульного теста, который пытается сохранить 'bar', он завершается неудачно и проверяет журналы, которые, как я вижу, NHibernate пытается сохранить объект bar в таблицу foo. Хотя я подозреваю, что это мои отображения, это может быть что-то еще, что я просто пропускаю.

Код, который создает фабрику сеанса (обратите внимание, я также пробовал отдельные вызовы в .Mappings):

Fluently.Configure().Database(MsSqlConfiguration.MsSql2008
    .ConnectionString(c => c
        .Server(@"localhost\SQLEXPRESS")
        .Database("foo")
        .Username("foo")
        .Password("foo")))
    .Mappings(m => 
        { 
            m.FluentMappings.AddFromAssemblyOf<FooMap>()
                .Conventions.Add(FluentNHibernate.Conventions.Helpers
                .Table.Is(x => "foos"));
            m.FluentMappings.AddFromAssemblyOf<BarMap>()
                .Conventions.Add(FluentNHibernate.Conventions.Helpers
                .Table.Is(x => "bars"));
        })
    .BuildSessionFactory();

Фрагмент юнит-теста:

using (var session = Data.SessionHelper.SessionFactory.OpenSession()) {      
   var bar = new Bar();
   session.Save(bar);
   Assert.NotNull(bar.Id);
}

Ответы [ 3 ]

2 голосов
/ 25 марта 2010

Вы делаете это неправильно. :)

Во-первых, m.FluentMappings.AddFromAssemblyOf<FooMap>() и m.FluentMappings.AddFromAssemblyOf<BarMap>() делают одно и то же (если FooMap и BarMap находятся в одной сборке). Каждый из них просто говорит Fluent NHibernate сканировать сборку, которая содержит универсальный тип; поэтому, если оба типа находятся в одной сборке, он будет сканировать ее дважды.

Во-вторых, вызов Conventions не ограничен конкретной сборкой, после которой он вызывается, он предназначен для всего набора сопоставлений. Итак, вы делаете два соглашения, которые устанавливают имя таблицы в явное значение, а второе - последнее, которое будет применено. Что вы хотите сделать, это использовать параметр x (который является типом сущности) и создать имя таблицы из этого.

Что вам нужно, это что-то вроде этого:

.Mappings(m => 
{ 
  m.FluentMappings.AddFromAssemblyOf<FooMap>()
   .Conventions.Add(Table.Is(x => x.Name + "s"));
})

Очевидно, что моя реализация наивна, и в зависимости от вашего соглашения об именах таблиц вы можете использовать мультипликатор (я думаю, у Касла есть такой, но найти его с помощью Google не составит труда).

Подробнее о условных обозначениях можно прочитать на Fluent NHibernate wiki .

0 голосов
/ 26 мая 2011

Просто хочу поделиться этим, автоматически добавится имя во множественном числе в зависимости от конечного алфавита. Не уверен насчет грамматики и некоторых исключений, но для меня это нормально. Любое исключение использует Table("foos"), как сказал @Lachlan Roche. Например. Клиент класс будет иметь Клиенты таблица и Категория класс будет иметь Категории таблица.

Модифицированный ответ @James Gregory:

.Mappings(m => 
{ 
  m.FluentMappings.AddFromAssemblyOf<FooMap>()
   .Conventions.Add(Table.Is(x => GetPluralName(x.Name));
})


public static string GetPluralName(string oldName)
{
    // This is the very simple. Just ignore exception like days, boys, photos and other specific nouns.
    if (oldName.EndsWith("y"))
        return oldName.Remove(oldName.Length - 1) + "ies";
    else if (oldName.EndsWith("s") || oldName.EndsWith("e") || oldName.EndsWith("h") || oldName.EndsWith("z") || oldName.EndsWith("o")) // Sibilant consonant or "o"
        return oldName + "es";
    return oldName + "s";
}
0 голосов
/ 25 марта 2010

С помощью classmap вы указываете имя таблицы в mapping . Если не указано, оно будет таким же, как имя класса сущности.

class FooMap : ClassMap<Foo>
{
    public FooMap()
    {
        Table("foos");
    }
}

Условные обозначения применяются ко всем отображениям. Поскольку вы добавили 2 соглашения об именах таблиц, только 1 вступит в силу.

Ваши FooMap и BarMap находятся в одной сборке? Вам нужно добавить каждую сборку только один раз.

.Mappings(m => m.FluentMappings.AddFromAssemblyOf<FooMap>())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...