Фильтры не применяются для многозначных ссылок - PullRequest
0 голосов
/ 09 сентября 2010

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

    public BarMap()
    {
        Table(DatabaseObject.UserBars);

        Id(x => x.Id, "Resource_Id");

        Map(x => x.ClientId, "Client_Id");
        Map(x => x.UserId, "User_Id");

        Map(x => x.Key, "Bar_Key")
            .Length(10);
        Map(x => x.Name, "Bar_Name")
            .Length(255);

У меня есть фильтр, примененный к классу, который должен выдать вПредложение WHERE, основанное на текущем контексте пользователя и клиента.Теперь на практике я вижу, что эти фильтры применяются, когда я пытаюсь получить Бар напрямую.Однако, когда я получаю объект с именем Foo, который ссылается на объект Bar, фильтры пропускаются во вторичном вызове SELECT.

public class FooMap : ClassMap<Foo>
{
    public FooMap()
    {
        Table(DatabaseObject.Foos);

        References<Bar>(x => x.Bar, "BarId")
            .PropertyRef(x => x.Key)
            .Cascade.None()
            .Fetch.Join()
            .NotFound.Exception();

Исходя из вышесказанного, вы ожидаете, что Foo выполнит JOIN для увлажнения объекта Bar, но, похоже, пропускает его и настаивает на получении объекта Foo.Я подозреваю, что вторичный вызов SELECT происходит, потому что библиотека NH пытается получить объект, основываясь на уникальном значении ключа (в журнале

Loader.Loader - SELECT this_.Id as Id12_2_, this_.ClientId as ClientId12_2_,  this_.BarId as BarId12_2_, Foo1_.Id as Id13_0_, Foo1_.ClientId as ClientId13_0_, Foo1_.Name as Name13_0_, Bar2_.Resource_Id as Resource1_4_1_, Bar2_.Client_Id as Client7_4_1_, Bar2_.User_Id as User8_4_1_, Bar2_.Bar_Key as Bar9_4_1_, Bar2_.Bar_Name as Bar10_4_1_ FROM Foos this_ inner join FooSchedules Foo1_ on this_.ScheduleId=Foo1_.Id inner join User_Bars Bar2_ on this_.BarId=Bar2_.Bar_Key and (Bar2_.Client_Id = :p0 OR Bar2_.Client_Id IS NULL) and Bar2_.User_Id = :p1 WHERE (Foo1_.ClientId = :p2 OR Foo1_.ClientId IS NULL) and (this_.ClientId = :p3 OR this_.ClientId IS NULL) AND Foo1_.Name = :p4 and Bar2_.Bar_Key = :p5 and Bar2_.Client_Id = :p6 and Bar2_.User_Id = :p7
Loader.Loader - processing result set
Loader.Loader - result set row: 0

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

Loader.Loader - result row: EntityKey[Core.Domain.FooSchedule#2929992], EntityKey[Core.Domain.Bar#470090], EntityKey[Core.Domain.Foo#3211664]
Loader.Loader - Initializing object from DataReader: [Core.Domain.FooSchedule#2929992]
Loader.Loader - Initializing object from DataReader: [Core.Domain.Foo#3211664]
Loader.Loader - done processing result set (1 rows)
Loader.Loader - total objects hydrated: 2
Engine.TwoPhaseLoad - resolving associations for [Core.Domain.FooSchedule#2929992]
Engine.Loading.LoadContexts - creating collection wrapper:[Core.Domain.FooSchedule.Foos#2929992]
Engine.TwoPhaseLoad - done materializing entity [Core.Domain.FooSchedule#2929992]
Engine.TwoPhaseLoad - resolving associations for [Core.Domain.Foo#3211664]
Engine.Loading.LoadContexts - creating collection wrapper:[Core.Domain.Foo.Items#3211664]

Здесь он пытается перегрузить панель, но не включает в себя фильтры, заставляющие его возвращать несколько строк / взрываться....

Loader.Entity.AbstractEntityLoader - Static select for entity Core.Domain.Bar: SELECT Bar0_.Resource_Id as Resource1_4_0_, Bar0_.Client_Id as Client7_4_0_, Bar0_.User_Id as User8_4_0_, Bar0_.Bar_Key as Bar9_4_0_, Bar0_.Bar_Name as Bar10_4_0_ FROM User_Bars Bar0_ WHERE Bar0_.Bar_Key=?
Loader.Loader - loading entity: [Core.Domain.Bar#ABFDBC01]
Engine.QueryParameters - BindParameters(Named:NHibernate.Type.StringType) ABFDBC01 -> [0]
Loader.Loader - SELECT Bar0_.Resource_Id as Resource1_4_0_, Bar0_.Client_Id as Client7_4_0_, Bar0_.User_Id as User8_4_0_, Bar0_.Bar_Key as Bar9_4_0_, Bar0_.Bar_Name as Bar10_4_0_ FROM User_Bars Bar0_ WHERE Bar0_.Bar_Key=:p0
Loader.Loader - processing result set

Я бы с радостью реорганизовал вид Bar в существующем виде, но временные ограничения его не допустят, если в этом нет крайней необходимости. Любые мысли о том, как заставить фильтры применяться? Или есть руководство о том, как делать контекстные ссылки на объекты?

На стороне JBoss я обнаружил, что Hibernate также мог пострадать от потенциально связанной проблемы проектирования .В коде источника NHibernate проблема, кажется, сосредоточена вокруг EntityJoinWalker:

SqlStringBuilder whereCondition = WhereString(Alias, uniqueKey, batchSize)
    //include the discriminator and class-level where, but not filters
    .Add(persister.FilterFragment(Alias, new CollectionHelper.EmptyMapClass<string, IFilter>()));

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

SqlStringBuilder whereCondition = WhereString(Alias, uniqueKey, batchSize)
    .Add(persister.FilterFragment(Alias, enabledFilters));

Справка?!

1 Ответ

0 голосов
/ 20 сентября 2010

Решено с помощью фильтрации в классе карты (новое в NH 2.1.2 по внешнему виду):

Where("Client_Id = :clientFilter.clientId AND User_Id = :userFilter.userId");
...