首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Session.Clear & Session.Merge问题

Session.Clear & Session.Merge问题
EN

Stack Overflow用户
提问于 2012-08-29 09:54:11
回答 1查看 1.3K关注 0票数 0

在我的应用程序中,我需要处理分离的对象,并且已经实现了reporitory模式。问题出现在以下代码示例中:

代码语言:javascript
运行
复制
var shops = ShopRepository.GetAll();           //Session.Clear() called inside, CacheMode = CacheMode.Ignore
var employees = EmployeeRepository.GetAll();   //same here

// Case 1: Session.Save() works, Session.Merge() irgnores the changes

employees.First().WorksAt.Name = "le new Shop in Town";
EmployeeRepository.Save(employees.First());

// Case 2: Session.Merge() works, Session.Save() throws NonUniqueObjectException

employees.First().WorksAt = employees.Last().WorksAt;
EmployeeRepository.Save(employees.First());

商店需要首先加载,因此用户可以通过ComboBox (或类似的东西)为员工设置“ComboBox”属性。

我的期望是,在调用Session.Clear()之后,nhibernate“忘记”所有实例(以及底层图)。情况并非如此。我仍然得到更新()-操作上的NonUniqueObjectException。因此,我无法使用SaveOrUpdate,尽管它很好地处理了对对象图所做的所有更改。

Session.Merge()只完成了一半的工作:

没有引发异常,保存了新的引用,但是对shop属性所做的更改没有保存(因为merge只是从缓存加载“旧”employee /shop对象并将employee属性复制到旧实例)。

我已经尝试过的是:

  • 将级联设置为“合并”
  • 在配置中禁用二级缓存
  • Session.Lock(myObj,LockMode.None)
  • Selfmade半合并:通过在Repository.Save()上反射Session.Merge()返回的对象重置所有引用
  • 重写等于()和GetHashCode()方法

该模型包含50个实体,因此(重新)在保存/更新会话中加载每个引用的bo实例不是一个选项。目前我使用的是nHibernate 3.3.0.4和FluentNHibernate 1.3。

是否有一个紧凑/优雅的解决方案来掩盖这两种情况?也许禁用NHibernate的内部标识跟踪将解决问题?

映射可能如下所示:

代码语言:javascript
运行
复制
public class Shop
{
public virtual Int Id  { get; set; };
public virtual string Name  { get; set; };

public virtual ISet<Employee> AllEmployees{ get; set; }

  public Shop()
  {
    AllEmployees = new HashedSet<Employee>();
  }
}

public class ShopMap: ClassMap<Shop>
{
  public ShopMap()
  {
    Id(x => x.Id);
    Map(x => x.Name);
  }

  HasMany(c => c.AllEmployees).Cascade.None().NotFound.Ignore();
}

public class Employee
{
public virtual Int Id  { get; set; };
public virtual string FirstName  { get; set; };
public virtual string SureName  { get; set; };

public virtual Shop WorksAt{ get; set; }

  public Employee()
  {
  }
}

public class EmployeeMap: ClassMap<Employee>
{
  public EmployeeMap()
  {
    Id(x => x.Id);
    Map(x => x.FirstName);
    Map(x => x.SureName);

    References(c => c.WorksAt).Cascade.SaveUpdate().Fetch.Join().NotFound.Ignore();
  } 
}

更新

下面是存储库基类中的Save()方法的代码:

代码语言:javascript
运行
复制
public static void Save(T pSaveObj)
{
  using (ISession session = GetSession())
  {
    using (ITransaction trans = session.BeginTransaction())
    {          
      // session.Save(pSaveObj);
      session.Save(session.Merge(pSaveObj));                                         
      session.Flush();
      session.Clear();
    }
  }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-08-29 13:43:28

好吧..。你完全滥用了NHibernate。在会议上,几乎从来没有人要求清空和冲洗。创建会话只是为了执行保存,您可以从第一级缓存中获得0的好处。事务在dispose上隐式回滚(如果没有提交),所以您实际上什么也不做。

如果我正确地理解了您的意图,您更希望有这样的代码:

代码语言:javascript
运行
复制
public static void Save(T pSaveObj)
{
  using (ISession session = GetSession())
  {
    using (ITransaction trans = session.BeginTransaction())
    {          
      session.SaveOrUpdate(pSaveObj);                                         
      trans.Commit()
    }
  }
}
  • 我假设pSaveObj没有附加到会话(如果附加了,那么使用session.Update)
  • 使用NH 仍然是不好的方式。
    • 如果您没有很强的理由使用存储库模式,忘记它并使用原始会话对象,它将为您节省上千个问题。

看看NH正在用sql分析器做什么。我觉得这是个很好的学习方法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12175237

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档