2017-01-18 31 views
0

我是从约12小时坚持了这个错误关联,以便可以在任何一个可以帮助我至少明白什么是错的NHibernate的非法企图的代理有两个打开的会话

这里是我的代码

public virtual void AssignAssets(IList<long?> assetsIds, ManualAssetAssignment<TAsset>.AssignmentMode mode, IQueryableRepository<TAsset, long?> assetRepository) 
{ 
    this.Assets.Clear(); 
    if (mode == AssignmentMode.Execlusion) 
    { 
     //IList<long?> includedAssetsIds = assetRepository.Find().Where(entity => !assetsIds.Contains(entity.Id)).Select(entity => entity.Id).ToList(); 
     IList<TAsset> includedAssets = assetRepository.Find().Where(entity => !assetsIds.Contains(entity.Id)).ToList(); 
     foreach (var asset in includedAssets) 
     { 
      this.Assets.Add(asset); 
     } 
    } 
    else 
    { 
     foreach (var assetId in assetsIds) 
     { 
      var asset = assetRepository.Get(assetId); 
      this.Assets.Add(asset); 
     } 
    } 
    _areAssetsEvaluated = true; 
} 

这里是我的测试

using (var tx = DataSessionContext.Session.BeginTransaction()) 
{ 
    atm = new Atm(AtmTestData.AutoCompleteCommand(new Atm.SetupCommand() { }), commandDependencyRegistry); 
    atmRepository.Save(atm); 
    List<long?> atmIds = new List<long?> { atm.Id }; 

    var command = AtmExpenseTestData.AutoCompleteCommand(new AssetExpense<Atm>.SetupCommand()); 
    expense = new AssetExpense<Atm> 
    (
     command, commandDependencyRegistry 
    ); 

    var assignCommand1 = new AssetExpense<Atm>.ManualAssetAssignmentCommand() 
    { 
     AssetsIds = new List<long?>() { atm.Id.Value }, 
     Mode = ManualAssetAssignment<Atm>.AssignmentMode.Execlusion 
    }; 
    assignCommand1.Execute(expense, commandDependencyRegistry); 
    atmAssetExpenseRepository.Save(expense); 

    tx.Commit(); 
} 

奇怪的是,如果我在代码替换这块

IList<TAsset> includedAssets = assetRepository.Find().Where(entity => !assetsIds.Contains(entity.Id)).ToList(); 
foreach (var asset in includedAssets) 
{ 
    this.Assets.Add(asset); 
} 

通过这个

IList<long?> includedAssetsIds = assetRepository.Find().Where(entity => !assetsIds.Contains(entity.Id)).Select(entity => entity.Id).ToList(); 
foreach (var assetId in includedAssetsIds) 
{ 
    this.Assets.Add(assetRepository.Get(assetId)); 
} 

如果我更换了错误消失,使任何人都可以帮助我了解此错误。

编辑 - 这可能是有益的

从堆栈跟踪我得到的例外条款应该从此方法抛出专门对13号线return (TId)((ISession)Session).Save(entity);

public virtual TId Save(TAggregateRoot entity, Action commitPostAction, Action rollbackPostAction, bool propagatePostActionError = false) 
{ 
    if (entity == null) 
    { 
     throw new ArgumentNullException("entity"); 
    } 

    if (entity is IValidatable) 
    { 
     ((IValidatable)entity).Validate(); 
    } 
    RegisterPostActions(commitPostAction, rollbackPostAction, propagatePostActionError); 
    if (Session is ISession) 
    { 
     return (TId)((ISession)Session).Save(entity); 
    } 
    else 
    { 
     return (TId)((IStatelessSession)Session).Insert(entity); 
    } 
} 
+0

你究竟是如何创建会话? –

回答

0

列表(IListISet ...)和实体的引用是NHibernate中的代理。这可以让你懒加载它们。异常告诉你在两个打开的会话中正在使用这个代理服务器之一。这意味着您正在一个会话中加载一个实体并尝试将其保存在另一个会话中。如果这是有意的,请在使用下一个会话之前关闭第一个会话。我会建议使用UnitOfWork模式来防止这种行为。

+0

我确定不同的时间,会话具有相同的会话Id是相同的使用DataSessionContext.Session – user3260672

+0

不幸的是NHibernate有另一种意见^^您可以尝试[NHibernate Profiler](https://www.hibernatingrhinos.com/products/nhprof )来检查打开的会话。对于每个使用NHibernate的开发人员来说,它的免费期限为30天,并且是不可或缺的工具。 – Rabban

+0

谢谢@Rabban – user3260672

相关问题