Вот моя (упрощенная) модель: Билет -> Обратный звонок (и) клиента
Мой Билет сопоставлен так, что когда он загружен, Обратные вызовы также.
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()
;
// ...
}