Краткое описание:
после того, как родитель и один из его дочерних элементов обновлены, транзакция зафиксирована, сеанс закрыт, следующий сеанс получает родительский элемент из кэша L2, но обновленный дочерний элемент загружается из базы данных. Родитель версирован, дети нет.
Подробное описание:
как я уже говорил, у меня есть родитель с дочерней коллекцией. Родитель версионен, но дочерние не соответствуют моему приложению, и сопоставления гарантируют, что все обновления выполняются путем сохранения родителя. Что я вижу, что, когда я загружаю parent с потомками, parent и большинство потомков загружаются из кэша L2, но недавно обновленный child загружается из базы данных. Я провел некоторое исследование деталей ReadWriteCache и обнаружил, что после того, как я сохранил parent и обновил child, следующий код решает НЕ обновлять кэш:
public bool Put(CacheKey key, object value, long txTimestamp, object version, IComparer versionComparator, bool minimalPut)
{
bool CS$1$0000;
if (txTimestamp == -9223372036854775808L)
{
return false;
}
lock (this._lockObject)
{
if (log.IsDebugEnabled)
{
log.Debug("Caching: " + key);
}
try
{
this.cache.Lock(key);
ILockable lockable = (ILockable) this.cache.Get(key);
if ((lockable == null) || lockable.IsPuttable(txTimestamp, version, versionComparator))
{
this.cache.Put(key, new CachedItem(value, this.cache.NextTimestamp(), version));
if (log.IsDebugEnabled)
{
log.Debug("Cached: " + key);
}
return true;
}
if (log.IsDebugEnabled)
{
if (lockable.IsLock)
{
log.Debug("Item was locked: " + key);
}
else
{
log.Debug("Item was already cached: " + key);
}
}
CS$1$0000 = false;
}
finally
{
this.cache.Unlock(key);
}
}
return CS$1$0000;
}
В моем случае lockable - это не null, но он не может быть вставлен:
public bool IsPuttable(long txTimestamp, object newVersion, IComparer comparator)
{
// we really could refresh the item if it
// is not a lock, but it might be slower
//return freshTimestamp < txTimestamp
return version != null && comparator.Compare(version, newVersion) < 0;
}
Как вы можете видеть из источника NHibernate, ранее решение IsPuttable было принято путем сравнения временных меток, но теперь версия вступает в игру.
Теперь вопрос: я должен версия КАЖДОЙ сущности в моей доменной модели? До того, как возникла проблема, я был уверен, что мне следует использовать только версию Aggregate Roots.
Я действительно рассчитываю найти другой способ решения этой проблемы, потому что моя иерархия родитель-потомок гораздо глубже (не спрашивайте почему :)), скажем, на 3 уровня (на самом деле она глубже):
Root-> ляющих> внучат
В сценарии, когда обновлялся только GrandChild, я ожидал 2 оператора UPDATE: один для GrandChild и другой для Root, чтобы обновить свою версию. Но если я сделаю версию Child, то это будет стоить мне дополнительных обновлений базы данных и туда-обратно :( ... Кстати, если ping Ayende или кто-то из NH - ADO.NET, пакетирование для NH работает только для тех же сущностей, оно не будет вставлено Операторы пакетного обновления для GrandChild, Child и Root.