2016-09-13 23 views
0

我想执行使用NHibernate的数据恢复,但我得到各种错误,从外键违规主要违规事件和之间的一切。为了给出一些背景知识,我创建了一个“Base”类,我的应用程序中的每个类都继承了这个类(请不要评论这个,这是我需要/想要的)。 因此,要执行备份,我只需拨打session.QueryOver<BaseClass>().List<BaseClass>()即可获取所有数据,并将其序列化为JavaScript,并将其压缩并保存。这就是我创建备份的方式。 现在恢复....NHibernate大容量恢复备份似乎不可能

我轻松地反序列化备份,得到正确的类型和一切。

我试过使用session.save(item, item.Id),把项目放回原来的数据库中,但NHibernate似乎并不喜欢这样,特别是当我在表(或类)之间有外键时。

浏览互联网,似乎我的答案会与无国籍的会议。我尝试了这些,但我仍然遇到各种各样的错误。

我尝试过的一件事是将所有的插入包装在try-catch中,然后重试,直到我不再收到错误。这种工作,但当我打电话session.Commit我收到了一个错误消息,有很多'违反主键约束'消息。我已将所有插入事件包装到1个事务中(写入时我正在考虑尝试取出事务)....没有事务处理,似乎已将某些的数据保存起来。我想我应该有一个交易,因为我希望能够保证所有数据都没有恢复,从而使恢复更加可靠。

使用try-catch似乎不可靠,也意味着我必须猜测howmany次重试插入操作对失败的项目。

我想添加的一个重要的注意事项是,当我的代码运行时,除了它们是类型为BaseClass的Id类型外,我对它们一无所知。所以一个给出错误的类是菜单类。它有一个属性是List<Menu> -childMenus和Menu -parentMenu类型的另一个属性。这两个属性映射使用流利nhibernate是HasManyReferences,这是我相信这些应该映射。这是对我造成问题的类,因为NHibernate创建了外键。我认为这很好,除了现在我无法轻松恢复。

如果我没有得到一个合适的答案或很快得出这个结论,我的解决方案将尝试和命令要恢复的项目,以便“看起来”像它可能有一个父对象(BaseClass类型的属性)与外键,我会将这些项目排序到列表中,并最后插入它们,并希望避免外键约束违规。

但我希望有其他的选择。

此外,当我做恢复时,Id生成器被设置为分配,所以我不认为我的问题与未知或无效的id有关。在原始数据中,我的ID是GUID。 (我可能会稍后将此更改为hilo整数,但每次只能解决一个问题)。

任何帮助将不胜感激。

在此先感谢...

回答

0

除非我想出一个更好的选择,我的解决方案将涉及暴力破解的数据存入数据库,使用类似于下面的代码:

  var existingCount = 0l; 
      var lastCount = -1l; 
      while (existingCount < items.Count) 
      { 
       using (var session = factory.OpenSession()) 
       { 
        existingCount = session.CreateCriteria<BaseClass>() 
              .SetProjection(Projections.RowCountInt64()) 
              .List<long>() 
              .Sum(); 
        session.Flush(); 
       } 

       if (existingCount == items.Count) 
       { 
        break; // success 
       } 

       if (lastCount == existingCount) 
       { 
        throw new Exception("Error restoring backup, no change after retrying inserting new items."); 
       } 
       lastCount = existingCount; 

       try 
       { 
        using (var session = factory.OpenSession()) 
        { 
         var existingItems = session.QueryOver<BaseClass>().List<BaseClass>().ToList(); 
         SaveItemsToDb(existingItems, items, session); // checks if item already exists, if not, tries to save it. Also has some try-catch processing 

         session.Flush(); 
        } 
       } 
       catch (Exception exception) 
       { 
        //Do nothing, just try again. 
       } 
      }