关于删除子对象的NHibernate StaleStateException

时间:2011-02-01 19:34:39

标签: c# .net database nhibernate fluent-nhibernate

是否有可能从StackTrace中说出此异常的起源?

StaleStateException:  Unexpected row count: 0; expected: 1

我在多个DataGridViews中显示父/子对象集合,并执行varioius add / delete / save命令。尝试删除子行/实体时会发生此异常。我使用 DefaultCascadeAll约定

在此异常之后,相应的父实体已从数据库中删除,即使没有调用它。所以在显示的图像中,下次我启动程序; Store Id = 55不存在。

计划窗口: http://img822.imageshack.us/img822/4686/ss20110201212511.png

StackTrace: http://img145.imageshack.us/img145/408/ss20110201211702.png

映射:

public class StoreMap : ClassMap<Store>
{
    public StoreMap()
    {
        Id(x => x.Id);
        Map(x =>  x.Name);
        HasMany(x => x.Staff)    
            .Inverse()            
            .Cascade.All();       
        HasManyToMany(x => x.Products)
            .Cascade.All()
            .Table("StoreProduct");    
    }

}

public class EmployeeMap : ClassMap<Employee> 
{

    public EmployeeMap()
    {
        Id(x => x.Id);                
        Map(x => x.FirstName);
        Map(x => x.LastName);
        References(x => x.Store);    
    }
}

EDIT1:

    private void btnDeleteEmployee_MouseDown(object sender, MouseEventArgs e)
    {
        var item = bsEmployees.Current;    // BindingSource
        Employee emp = new Employee();

        if (item.GetType() == emp.GetType())
        {
           emp = (Employee)bsEmployees.Current;
           EmployeeRepository.Delete(emp);
        }            
    }

2 个答案:

答案 0 :(得分:0)

要修复您似乎不想要的级联,请将映射更改为Cascade.None

要快速修复陈旧状态,请执行以下操作:

private void btnDeleteEmployee_MouseDown(object sender, MouseEventArgs e)
{
    if (item.GetType() == emp.GetType())
    {
       emp = EmployeeRepository.GetById(((Employee)beEmployees.Current).Id);
       EmployeeRepository.Delete(emp);
    }            
}

这是一个可怕的设计,但也许足以让你在错过之后找到一个更好的设计。

HTH,
Berrryl

答案 1 :(得分:0)

此异常的可能原因是存储库方法无法处理(拒绝)临时实体,也可能是分离的实体未附加到会话。所以下面的代码修复了这一点,并避免了StaleStateExceptions。

正如所指出的那样,这个短会话范围对大多数情况来说并不是一个好的解决方案。

    public static void Delete(Employee employee)
    {
        using (ISession session = FNH_Manager.OpenSession())
        {
            using (ITransaction transaction = session.BeginTransaction())
            {
                if (Employee.Id != 0)
                {
                  var emp =  session.Get(typeof(Employee), employee.Id);

                  if (emp != null)
                  {
                    session.Delete(emp);
                    transaction.Commit();
                  }
                }
            }
        }
    }