Когда я пытаюсь добавить объект в хранилище я получаю NHibernate.TransientObjectException
с сообщением:NHibernate: объект ссылается на несохраненный переходный экземпляре
объекта ссылается несохраненным переходную экземпляра - сохранить переходный экземпляр перед промывкой или установить каскад действие для свойства на то, что сделало бы его автосохранением. Тип: MyApp.Domain.Model.Task
Я использую:
- NHibernate 3.3.1
- FluentNHibernate 1,4
- Microsoft Unity 2.1.505
Метод в репозитории более или менее выглядит следующим образом (я представляю здесь объединенную версию):
public void Add(T item)
{
if (!GetSession().Query<T>().Contains(item)) //generates the error, if commented out works fine
{
try
{
GetSession().BeginTransaction();
GetSession().Save(item);
GetSession().CommitTransaction();
}
catch
{
//rollback code
}
}
}
Важно то, что объект, который я пытаюсь сохранить в репозитории, не имеет ссылок и/или отношений с другими объектами. Это довольно простой объект. Следует отметить, что он расширяет объект DomainObject с идентификатором типа Guid.
Я использую схему первого кода, поэтому моя БД создается на основе моего кода. Из-за наследства (каждый объект распространяется DomainObject) Я использую UseUnionSubclassForInheritanceMapping()
Весь трассировки стека выглядит следующим образом:
w NHibernate.Engine.ForeignKeys.GetEntityIdentifierIfNotUnsaved(String entityName, Object entity, ISessionImplementor session)
w NHibernate.Type.EntityType.GetIdentifier(Object value, ISessionImplementor session)
w NHibernate.Type.ManyToOneType.NullSafeSet(IDbCommand cmd, Object value, Int32 index, ISessionImplementor session)
w NHibernate.Param.NamedParameterSpecification.Bind(IDbCommand command, IList`1 multiSqlQueryParametersList, Int32 singleSqlParametersOffset, IList`1 sqlQueryParametersList, QueryParameters queryParameters, ISessionImplementor session)
w NHibernate.Param.NamedParameterSpecification.Bind(IDbCommand command, IList`1 sqlQueryParametersList, QueryParameters queryParameters, ISessionImplementor session)
w NHibernate.SqlCommand.SqlCommandImpl.Bind(IDbCommand command, ISessionImplementor session)
w NHibernate.Loader.Loader.PrepareQueryCommand(QueryParameters queryParameters, Boolean scroll, ISessionImplementor session)
w NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
w NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
w NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)
w NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters)
w NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet`1 querySpaces, IType[] resultTypes)
w NHibernate.Hql.Ast.ANTLR.Loader.QueryLoader.List(ISessionImplementor session, QueryParameters queryParameters)
w NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.List(ISessionImplementor session, QueryParameters queryParameters)
w NHibernate.Engine.Query.HQLQueryPlan.PerformList(QueryParameters queryParameters, ISessionImplementor session, IList results)
w NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters queryParameters, IList results)
w NHibernate.Impl.AbstractSessionImpl.List(IQueryExpression queryExpression, QueryParameters parameters)
w NHibernate.Impl.ExpressionQueryImpl.List()
w NHibernate.Linq.DefaultQueryProvider.ExecuteQuery(NhLinqExpression nhLinqExpression, IQuery query, NhLinqExpression nhQuery)
w NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)
w NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression)
w System.Linq.Queryable.Contains[TSource](IQueryable`1 source, TSource item)
w MyApp.Data.Nhibernate.Fluent.Repository`1.Add(T item) w f:\Projects\MyApp\MyApp.Data.Nhibernate.Fluent\Repository.cs:wiersz 75
w MyApp.Domain.Services.Impl.CatalogServices.CreateTask(Task task) w f:\Projects\MyApp\MyApp.Domain.Services\Impl\CatalogServices.cs:wiersz 51
Я был бы признателен за вашу помощь
С наилучшими пожеланиями, Себастьян
OK, спасибо за воспроизведение. Меня беспокоит такая конструкция, как если бы (! GetSession(). Query() .Contains (item)) в хранилище add methos имеет смысл. Я мог бы либо сменить оператор if, чтобы сначала проверить идентификатор empry, а затем проверить на query.constains. Но это необходимо? Двигатель БД будет повышаться, если кто-то попытается сохранить объект с дублирующимся идентификатором. –
Нет, я бы этого не сделал, если не был нужен дизайнерское решение или что-то ... Я имею в виду, что в конце это еще один раунд DB, если объект еще не загружен правильно. Таким образом, это может даже вызвать проблемы с производительностью ... Тогда обычно вы должны знать, когда нужно вызывать сохранение, обновление, слияние или SaveOrUpdate в тот момент, когда вы на самом деле пытаетесь что-то сэкономить.Я бы не стал обманывать это от ответственности исполнителя. – MichaC