Критерии NHibernate: как исключить определенные сопоставленные свойства / коллекции? - PullRequest
1 голос
/ 21 июля 2011

Вот моя (упрощенная) модель: Билет -> Обратный звонок (и) клиента

Мой Билет сопоставлен так, что когда он загружен, Обратные вызовы также.

        base.HasMany<TechSupportCallback>(x => x.Callbacks)  
            .KeyColumn(Fields.TRACKED_ITEM_ID)
            .Not.LazyLoad()
            .Inverse()
            .Cache.ReadWrite();

Это не ленивая загрузка, потому что в противном случае я получу «нет сеанса для загрузки сущностей», когда веб-служба попытается сериализовать (и загрузить) прокси. (Использование репозиториев для извлечения данных.)

Это также двунаправленный .. (в CallbackMap)

        base.References(x => x.Ticket)
            .Column(Fields.TRACKED_ITEM_ID)
            .Not.Nullable();

Теперь ... нам нужно показать агенту список их обратных вызовов - ПРОСТО их обратные вызовы. - Когда я делаю запрос с использованием критериев для обратных вызовов, я не могу предотвратить загрузку билета (и, следовательно, всего его графика, включая другие коллекции). Ранее я пытался установить FetchMode.Lazy, затем выполнять итерацию каждого полученного обратного вызова и устанавливать для Ticket значение null, но это, похоже, игнорируется.

             // open session & transaction in using (..)
                var query = session.CreateCriteria<TechSupportCallback>()
                    .SetCacheable(true)
                    .SetCacheRegion("CallbacksByUserAndGroups")
                    .SetFetchMode("Ticket", FetchMode.Lazy) // <-- but this doesn't work!
                    .SetMaxResults(AegisDataContext.Current.GetMaxRecordCount())
                    ;
                rValue = query.List<TechSupportCallback>();
                rvalue.ForEach(x => x.Ticket = null;); // <-- since this is already retrieved, doing this merely prevents it from going back across the wire
                tx.Commit();
             // usings end (..)

Должен ли я делать это с проекцией вместо этого? Проблема в том, что .. я не смог найти пример проекций, используемых для заполнения сущности, или их список - только для использования в качестве подзапроса дочерней сущности или чего-то подобного для ограничения список родительских объектов.

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


[EDIT]

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

Я получаю следующее: (это было из-за ошибки, и с тех пор я прекратил использовать кеш, и он работает. http://nhibernate.jira.com/browse/NH-1090)

System.InvalidCastException occurred
  Message=Unable to cast object of type 'AEGISweb.Data.Entities.TechSupportCallback' to type 'System.Object[]'.
  Source=NHibernate
  StackTrace:
       at NHibernate.Cache.StandardQueryCache.Put(QueryKey key, ICacheAssembler[] returnTypes, IList result, Boolean isNaturalKeyLookup, ISessionImplementor session)
  InnerException: 

в

 rValue = query.List<TechSupportCallback>();

со списком проекций, определенным как

 // only return the properties we want!
 .SetProjection(Projections.ProjectionList()
     .Add(Projections.Alias(Projections.Id(), ex.NameOf(x => x.ID))) // 
     .Add(Projections.Alias(Projections.Property(ex.NameOf(x => x.ContactID)), ex.NameOf(x => x.ContactID)))
     // ...
  )
  .SetResultTra...;
  rValue = query.List<TechSupportCallback>();

отображается как

    public TechSupportCallbackMap()
    {
        base.Cache.ReadWrite();
        base.Not.LazyLoad();

        base.Table("TS_CALLBACKS");

        base.Id(x => x.ID, Fields.ID)
            .GeneratedBy.Sequence("SEQ_TS_CALLBACKS");

        base.References(x => x.Ticket)
            .Column(Fields.TRACKED_ITEM_ID)
            .Not.Nullable();

        base.Map(x => x.TrackedItemID, Fields.TRACKED_ITEM_ID)
            .Not.Insert()
            .Not.Update()
            .Generated.Always()
            ;
        // ...
     }

1 Ответ

3 голосов
/ 21 июля 2011

Похоже, что это работа именно для проекций.

var query = session.CreateCriteria<TechSupportCallback>()
                    .SetCacheable(true)
                    .SetCacheRegion("CallbacksByUserAndGroups")
                    .SetFetchMode("Ticket", FetchMode.Lazy)
                    .SetMaxResults(AegisDataContext.Current.GetMaxRecordCount())
                    .SetProjection(Projections.ProjectionList().
                                         .Add(Projections.Alias(Projections.Id(), "Id")
                                         .Add(Projections.Alias(Projections.Property("Prop"), "Prop")))
                    .SetResultTransformer(Transformers.AliasToBean<TechSupportCallback>())
                    ;

Просто перечислите все свойства, которые вы хотите включить, и исключите сущность Ticket.Вы даже можете создать класс POCO просто для инкапсуляции результатов этого запроса.Вместо использования существующего класса сущности.

...