2014-01-06 5 views
1

Когда я пытаюсь добавить объект в хранилище я получаю 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 

Я был бы признателен за вашу помощь

С наилучшими пожеланиями, Себастьян

ответ

3

Вы просто не можете запросить объект, который не имеет безопасности, поскольку он не имеет идентификатора.

Чтобы запросить этот объект, NHibernate попытается выяснить идентификатор объекта. Это работает только на сохраненных или переходных объектах, которые сохраняются.

Не сохраненные объекты не имеют идентификатора. Поэтому, если тип ID - int, значение будет равно нулю. В вашем случае я думаю, что это будет Guid.Empty, потому что Guid не может быть нулевым. Просто проверьте это вместо этого.

Вы также можете определить, что несохраненное значение в пределах отображения должно быть на 100% уверенным;). Но он также должен работать по умолчанию с Guid или int. Отображение может использоваться для пользовательских типов и т. Д.

Id(x => x.Id).UnsavedValue(0); 
+0

OK, спасибо за воспроизведение. Меня беспокоит такая конструкция, как если бы (! GetSession(). Query () .Contains (item)) в хранилище add methos имеет смысл. Я мог бы либо сменить оператор if, чтобы сначала проверить идентификатор empry, а затем проверить на query.constains. Но это необходимо? Двигатель БД будет повышаться, если кто-то попытается сохранить объект с дублирующимся идентификатором. –

+0

Нет, я бы этого не сделал, если не был нужен дизайнерское решение или что-то ... Я имею в виду, что в конце это еще один раунд DB, если объект еще не загружен правильно. Таким образом, это может даже вызвать проблемы с производительностью ... Тогда обычно вы должны знать, когда нужно вызывать сохранение, обновление, слияние или SaveOrUpdate в тот момент, когда вы на самом деле пытаетесь что-то сэкономить.Я бы не стал обманывать это от ответственности исполнителя. – MichaC

Смежные вопросы

 Смежные вопросы