#c# #linq #nhibernate #nhibernate-mapping
#c# #linq #nhibernate #nhibernate-сопоставление
Вопрос:
У меня есть объект, который содержит список объектов.
public class Product: IProduct
{
public virtual long Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<IFunction> Functions { get; set; }
}
public class Function : IFunction
{
public virtual long Id { get; set; }
public virtual string Name { get; set; }
public virtual IProduct Product { get; set; }
}
Сопоставленный список объектов ( IList < IFunction > ):
<bag name="Functions" cascade="all" table="T_WEBFUNCTIONS" lazy="false">
<key column="PRODUCT_ID" />
<one-to-many class="Function" />
</bag>
Код :
Я пытаюсь создать новый объект продукта
public IProduct SetProduct(string productName)
{
// Product repository, which have nhibernate opened session ( ISession )
IDBRepository<IProduct> rep = Repository.Get<IProduct>();
// Create new object of product
rep.Create(new Product() { Name = productName });
// get created object by name
prod = rep.Query().Where(x => x.Name == productName).SingleOrDefault();
// I HAVE ISSUE HERE
// prod.Functions == NULL. It must be a new List<Function>()
// Nhibernate don't create empty list for me and this property always null
return prod;
}
НО. Когда сеанс nhibernate закроется и откроется снова, список будет создан и будет содержать 0 элементов.
Если я создам объект (продукт) в том же сеансе и получу его после создания, bag будет иметь значение null.
Функция хранилища данных
public class DBRepository<T> : IDBRepository<T>
{
protected ISession CurrentSession;
public DBRepository(ISession session)
{
CurrentSession = session;
}
public void Create(T obj)
{
var tmp = CurrentSession.BeginTransaction();
CurrentSession.Save(obj);
tmp.Commit();
}
}
Ответ №1:
Когда вы вызываете new Product()
, ваш код создает экземпляр объекта, и свойство List<> начинает свою жизнь как null . NHibernate не может вам здесь помочь — это то, что вы решили сделать (не переопределяя c’torпо умолчанию).
Кэш 1-го уровня NHibernate (краткое объяснение здесь) сохраняет ваш объект при фиксации транзакции, поэтому, когда в том же открытом сеансе вы запрашиваете объект по его идентификатору, NHibernate пропускает получение объекта из базы данных и предоставляет вам тот же созданный экземпляр объекта. Вы можете проверить это с Object.ReferenceEquals(prodYouCreated, prodRetrievedFromRepository)
помощью .
При закрытии сеанса кэш 1-го уровня очищается, и при следующем запросе NHibernate извлекает данные и создает сам объект — он возвращает вам список нулевой длины вместо null. Это поведение по умолчанию.
Надеюсь, это поможет,
Джонно
Комментарии:
1. спасибо. это помогло. Пробовал использовать выражение
rep.Create(new Product() { Name = productName, Functions = new List<IFunction>() })
. Работает хорошо2. Не беспокойтесь. Определенно лучше пойти с
Functions = new List<IFunction>()
, чем с изменением c’tor’а! Мне только что пришло в голову, что «пропускает получение объекта из базы данных» в некоторых случаях верно, но не здесь. В этом случае информация уже была извлечена из базы данных (это зависит от запроса, выполненного в репозитории), поэтому сохраняется только повторное построение объекта NHibernate.