Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 课时.清除&;会话。合并问题_C#_Nhibernate_Fluent - Fatal编程技术网

C# 课时.清除&;会话。合并问题

C# 课时.清除&;会话。合并问题,c#,nhibernate,fluent,C#,Nhibernate,Fluent,在我的应用程序中,我需要处理分离的对象,并且已经实现了reporitory模式。以下代码示例中显示了这些问题: var shops = ShopRepository.GetAll(); //Session.Clear() called inside, CacheMode = CacheMode.Ignore var employees = EmployeeRepository.GetAll(); //same here // Case 1: Session.Save()

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

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());
首先需要加载商店,因此用户可以通过组合框(或类似的东西)为员工设置“WorksAt”属性

我的期望是,nhibernate在调用Session.Clear()之后“忘记”所有实例(以及底层图形)。事实并非如此。在Update()-操作中,我仍然不断得到UnuniqueObjectException。因此,我不能使用SaveOrUpdate,尽管它可以很好地处理对对象图所做的所有更改

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

未引发异常,保存了新引用,但对店铺属性所做的更改不会保存(因为merge只是从缓存加载“旧”员工/店铺对象,并将员工属性复制到旧实例)

我已经尝试过的:

  • 将级联设置为“合并”
  • 在配置中禁用二级缓存
  • Session.Lock(myObj,LockMode.None)
  • 自制半合并:通过Session.merge()返回的对象在Repository.Save()上的反射重置所有引用
  • 重写Equals()和GetHashCode()方法
该模型包含约50个实体,因此在保存/更新时(重新)加载会话中的每个引用bo实例不是一个选项。目前我正在使用nHibernate 3.3.0.4和FluentNHibernate 1.3

是否有一个紧凑/优雅的解决方案可以覆盖这两种情况? 也许禁用NHibernate的内部id跟踪可以解决问题

映射可能如下所示:

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();
  } 
}
public static void Save(T pSaveObj)
{
  using (ISession session = GetSession())
  {
    using (ITransaction trans = session.BeginTransaction())
    {          
      session.SaveOrUpdate(pSaveObj);                                         
      trans.Commit()
    }
  }
}

嗯。。你完全误用了NHibernate。在会话中几乎从不调用Clear和Flush。仅为执行save而创建会话可使您从一级缓存中获得0个好处。事务在dispose上隐式回滚(若并没有提交),所以您实际上什么也不做

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

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();
  } 
}
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分析器做了什么。我发现这是一个很好的学习方法。

在实际应用中花了一段时间使用这种方法后:pkmiec完全正确,当涉及NH时,真的不使用存储库模式(或分离的业务对象)。改为使用工作单元,并将匹配的poco添加到您的设计中