Фильтр Nhibernate не применяется последовательно к дочерним коллекциям - PullRequest
3 голосов
/ 23 февраля 2011

У меня есть сущность с дочерними объектами, которые мягко удаляются.Когда я вызываю простой метод get для родительского элемента, я хочу получить его для дочерних объектов, которые не были удалены.У всех моих сущностей есть базовый класс, в котором хранятся поля id, audit, soft delete.

Для этого я создал 2 прослушивателя событий и 1 фильтр, один прослушиватель событий будет каскадно удалять при необходимости,и другой, чтобы применить фильтр к предзагрузке.

public class NonDeletedFilter : FilterDefinition
{
    public static string FilterName = "NonDeletedFilter";
    public NonDeletedFilter()
    {
        WithName(FilterName).WithCondition("IsDeleted = 0");
    }
}

public class ParentMap : IAutoMappingOverride<Parent>
{
    public void Override(FluentNHibernate.Automapping.AutoMapping<Parent> mapping)
    {
        mapping.HasMany(x => x.Children).Fetch.Join()
                .Inverse()
                .Cascade.AllDeleteOrphan()
                .ApplyFilter(NonDeletedFilter.FilterName);
    }
}

public class PreLoadEventListener : DefaultPreLoadEventListener
{
    public override void OnPreLoad(NHibernate.Event.PreLoadEvent preloadEvent)
    {
        preloadEvent.Session.EnableFilter(NonDeletedFilter.FilterName);
        base.OnPreLoad(preloadEvent);
    }
}

Вот проблема, и это худший вариант: иногда это работает.В моих тестовых случаях он создает sql отлично.Он выбирает родителя, имеет левое внешнее соединение для дочернего элемента и удостоверяется, что дочерние элементы isdeleted = false.В моем приложении это не так, это просто делает соединение без проверки.Он работает на отдельных отношениях родитель / потомок с тем же примененным переопределением сопоставления.

Конфигурация построена из тех же сопоставлений, имеет те же фильтры и прослушиватели событий.Единственное отличие, которое я вижу, состоит в том, что в моем тесте используется база данных sqlite db, в которой база данных создается на основе сопоставлений, а затем выполняется инициализация sql для предварительного заполнения базы данных.Но он заполнен фактическими данными, и я не могу найти никаких отличий.

В этот момент я предполагаю, что мой вопрос - где мне искать?

Вот мои мысли.Не правы ли таблицы?Они выглядят хорошо.Что-то упускает из сопоставления?Они выглядят одинаково.Фильтр не применяется?Ну это для другого.Фильтр работает?Это для другого.

Возможно, я так много смотрел на код, что не вижу проблемы.Может ли кто-нибудь пролить свет на то, где сосредоточить свои усилия?

1 Ответ

0 голосов
/ 23 февраля 2011

После нескольких ошеломляющих часов проблема наконец-то проявилась. У меня есть базовый вызов хранилища, чтобы применить операторы выборки к свойствам. Для сломанного класса репозиторий извлекал то же свойство, переопределяя фильтр, установленный в классе карты. И да, я слишком долго смотрел на это, чтобы заметить разницу. Другой установил глаза, работающие через него, и заметил рабочий, идущий по хранилищу другим путем. Итак, +1 для парного программирования.

И для тех, кто интересуется, почему прослушиватель событий предварительной загрузки не работает, убедитесь, что при создании пользовательских критериев вы не переопределяете стратегию извлечения.

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

Вот пример того, что было сделано в хранилище.

public override Parent Get(id)
{
    Session.CreateCriteria<Parent>()
           .Fetch<Parent>(x => x.Children)
}

public static ICriteria Fetch<T>(this ICriteria criteria, params Expression<Func<T, object>>[] fetch)
{
    foreach (Expression<Func<T, object>> expression in fetch)
        criteria.SetFetchMode(expression, FetchMode.Join);

    return criteria;
}

Включен метод расширения для очистки кода при создании пользовательских критериев.

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