У меня есть сущность с коллекцией, которая содержит другие сущности, имеющие больше ссылок на сущности. Когда сущность загружается и позже обновляется, запускается отложенная коллекция, и из базы данных извлекается много материала, который мне не нужен. Итак, как я могу предотвратить запуск неинициализированных обновлений при обновлении?
Я написал небольшой тест, который показывает это.
class SimpleClass
{
public virtual int Id { get; set; }
public virtual IList<ChildClass> Childs { get; set; }
}
class ChildClass
{
public virtual int Id { get; set; }
}
class SimpleClassMap : ClassMap<SimpleClass>
{
public SimpleClassMap()
{
Id(sc => sc.Id).GeneratedBy.Assigned();
HasMany(sc => sc.Childs)
.Cascade.All()
.LazyLoad();
}
}
class ChildClassMap : ClassMap<ChildClass>
{
public ChildClassMap()
{
Id(cc => cc.Id).GeneratedBy.Assigned();
}
}
и следующий тест
[Fact]
public void Test()
{
m_session.Save(new SimpleClass
{
Id = 1,
Childs = new List<ChildClass>
{
new ChildClass { Id = 1 },
new ChildClass { Id = 2 },
new ChildClass { Id = 3 },
}
});
m_session.Flush();
m_session.Clear();
log.Debug("Start Test");
var simple = m_session.Get<SimpleClass>(1);
var persistentcollection = simple.Childs as IPersistentCollection;
Assert.False(persistentcollection.WasInitialized, "Before Refresh, collection should not be initialized but was");
log.Debug("Refresh");
m_session.Refresh(simple);
Assert.False(persistentcollection.WasInitialized, "After Refresh, collection should not be initialized but was");
}
Выход:
После обновления коллекция не должна быть инициализирована, но была
Просто чтобы уточнить:
Может быть, я могу жить без удаления в cascade.all, но определенно не без cascade.refresh.
Я хочу обновить каскад для коллекции, если она инициализирована, иначе нет, потому что при использовании она будет загружена свежими данными.
Я немного поиграл с NHibernate-кодом для события Refresh. Если я удалю профиль извлечения:
DefaultRefreshEventListener {
public virtual void OnRefresh(RefreshEvent @event, IDictionary refreshedAlready)
{
[...]
string previousFetchProfile = source.FetchProfile;
//source.FetchProfile = "refresh";
object result = persister.Load(id, obj, @event.LockMode, source);
//source.FetchProfile = previousFetchProfile;
[...]
}
я получаю то, что ожидаю в журналах (удаленные псевдонимы в SQL):
без инициализации коллекции
Session.Get
DEBUG - SELECT Id FROM "SimpleClass" WHERE Id=:p0;:p0 = 1
Refresh
DEBUG - SELECT Id FROM "SimpleClass" WHERE Id=:p0;:p0 = 1
с инициализирующей коллекцией (simple.Childs.Count ();)
Session.Get
DEBUG - SELECT Id FROM "SimpleClass" WHERE Id=:p0;:p0 = 1
simple.Childs.Count();
DEBUG - SELECT SimpleClass_id, Id, Id FROM "ChildClass" WHERE SimpleClass_id=:p0;:p0 = 1
Refresh
DEBUG - SELECT Id FROM "ChildClass" WHERE Id=:p0;:p0 = 1
DEBUG - SELECT Id FROM "ChildClass" WHERE Id=:p0;:p0 = 2
DEBUG - SELECT Id FROM "ChildClass" WHERE Id=:p0;:p0 = 3
DEBUG - SELECT Id FROM "SimpleClass" WHERE Id=:p0;:p0 = 1
Я все еще не уверен в других последствиях этого