NHibernate и наследование создают неожиданное поведение двойного запроса? - PullRequest
4 голосов
/ 30 июня 2010

Я использую FluentNHibernate.Я не использую автоматическое отображение.У меня есть базовый класс, который подкласс.Когда я выполняю запрос к базовому классу, он выполняет дополнительный запрос к подклассу.Вот (надуманный) пример того, что я делаю:

public class Foo
{
    int Id;
    string SomeValue;
}

Я создаю другой класс, который представляет запись аудита первой, и я наследую ее:

public class FooAudit : Foo
{
    DateTime DateModified;
}

Я создаюотдельные сопоставления для каждой из них, которые идут в свои таблицы:

public class FooMap : ClassMap<Foo>
{
    public FooAuditMap()
    {
        Table("Foo");
        Id(x => x.Id).Column("FOO_ID");
        Map(x => x.SomeValue).Column("SOME_VALUE");
    }
}

public class FooAuditMap : ClassMap<FooAuditMap>
{
    public FooAuditMap()
    {
        Table("FooAudit");
        CompositeId()
            .KeyProperty(x => x.DateModified, c => c.ColumnName("AUDIT_DATE"));
            .KeyProperty(x => x.Id, c => c.ColumnName("FOO_ID"));
        Map(x => x.SomeValue).Column("SOME_VALUE");
    }
}

Я выполняю запрос к Foo:

public virtual IEnumerable<Foo> List()
{
    using (var session = SessionFactory.OpenSession())
    {
        return session.CreateCriteria<Foo>().List<Foo>();
    }
}

, который затем дважды обращается к БД, один раз для выполнения этого запроса к Fooи снова в FooAudit.

Почему он делает два запроса?Я сгенерировал файлы HBM, и эти классы абсолютно ничего не связывают.

РЕДАКТИРОВАТЬ: Для полноты вот как выглядит конфигурация начальной загрузки.

public static ISessionFactory CreateSessionFactory()
{
    return Fluently
        .Configure()
        .Database
        (
            FluentNHibernate.Cfg
            .Db.MsSqlConfiguration.MsSql2005
            .ConnectionString(GetConnectionString())
        )
        .Mappings(m => m
            .FluentMappings.AddFromAssemblyOf<Foo>()
            .Conventions.Add(typeof(EnumConvention)))
        .BuildSessionFactory();
}

Ответы [ 2 ]

4 голосов
/ 01 июля 2010

То, что вы видите, - это ожидаемое поведение.

Запрос к базовому классу также запрашивает все унаследованные классы.

Если для этого есть явное отображение NHibernate (подкласс, join-subclass,и т.д.) это будет только один запрос.В противном случае, это считается неявно полиморфным определением, и выдается два запроса для получения результатов от всех из них.

Я считаю (из документов; я не пробовал), что вы можете избежать этого, сопоставив классс polymorphism="explicit".Я не знаю, поддерживает ли Fluent это.

0 голосов
/ 30 июня 2010

Попробуйте:

public class FooAuditMap : SubclassMap<FooAudit>
{
    public FooAuditMap()
    {
        Table("FooAudit");
        CompositeId()
            .KeyProperty(x => x.DateModified, c => c.ColumnName("AUDIT_DATE"));
            .KeyProperty(x => x.Id, c => c.ColumnName("FOO_ID"));
        Map(x => x.SomeValue).Column("SOME_VALUE");
    }
}

У вас все еще есть проблема, потому что идентификаторы Foo и FooAudit отличаются.Если FooAudit является подклассом Foo, у него должен быть тот же идентификатор, который хранится в таблице Foo.

Обновление на основе комментария OP: Вы, безусловно, можете иметь цепочку наследования в модели домена, не выражая ее в NHibnerate.Просто измените FooAuditMap для наследования ClassMap<FooAudit>.Однако ваш запрос на объект типа Foo не будет включать в себя какие-либо типы FooAudit, потому что NH не знает об этом отношении.

Но я думаю, что у вас есть отношение один ко многим - у Foo естьколлекция FooAudits - и вы должны отобразить ее таким образом.

Обновление 2: похоже, мое предыдущее утверждение «Однако ваш запрос для объекта типа Foo не будет включать в себя какие-либо типы FooAudit, потому что NH не знает оотношения."неправильно.Есть способ вернуть только базовый класс, ограничив результаты с помощью свойства special class , но это не очень удачное решение.

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

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