2016-09-13 2 views
0

Я пытаюсь выполнить восстановление данных с помощью NHibernate, но я получаю всевозможные ошибки, от нарушений внешнего ключа до нарушений первичного ключа и всего между ними.NHibernate массовое восстановление резервной копии кажется невозможным

Чтобы дать некоторый фон, я создал класс «Base», из которого наследуется каждый класс моего приложения (пожалуйста, не комментируйте это, это то, что мне нужно/нужно). Итак, чтобы выполнить резервное копирование, я просто вызываю session.QueryOver<BaseClass>().List<BaseClass>(), и я получаю все данные, сериализую его на javascript, застегиваю на него и сохраняю. Вот как я создаю резервные копии. Теперь восстановление ....

Я легко десериализую резервную копию, получаю нужные типы и все такое.

Я попытался использовать session.save(item, item.Id), чтобы вернуть элементы с теми же идентификаторами, что и в исходной базе данных, но NHibernate, похоже, не нравится, особенно когда у меня есть внешние ключи между таблицами (или классами).

Просматривая Интернет, кажется, что мои ответы будут связаны с сеансами без гражданства. Я пробовал это, но у меня все еще есть всевозможные ошибки.

Одна вещь, которую я пытался, - это обернуть все вставки в try-catch и повторить попытку, пока я больше не получу ошибок. Этот вид работал, но когда я звоню session.Commit, я получаю сообщение об ошибке с большим количеством «Нарушение ограничения PRIMARY KEY» сообщений. Я завернул все мои вставки в одну транзакцию (при написании этого я думаю, чтобы попытаться вывести транзакцию) .... Без транзакции, похоже, сэкономил около данных. Я думаю, что у меня должна быть транзакция, так как я хочу быть в состоянии гарантировать, что все или ни одна из данных не была восстановлена, чтобы сделать восстановление более надежным.

Использование try-catch не кажется надежным, также это означает, что я должен угадать, сколько раз повторять попытку вставки в случае неудачных элементов.

Одним из важных замечаний, которые я хочу добавить, является то, что когда мой код работает, я ничего не знаю о классах или типах, отличных от типа BaseClass, с полем Id. Таким образом, один класс, который дает ошибку, представляет собой Меню. Он имеет свойство, которое находится List<Menu> -childMenus и другое имущество типа Menu -parentMenu. Эти 2 свойства отображаются с использованием безводного nhibernate равным HasMany и References, так я считаю, что они должны отображаться. Это класс, который вызывает проблемы для меня, потому что NHibernate создал внешние ключи. Это хорошо, на мой взгляд, за исключением того, что теперь я не могу сделать восстановление легко.

Если я не получу подходящего ответа или не выясню это в ближайшее время, мое решение будет состоять в том, чтобы попытаться упорядочить элементы, подлежащие восстановлению, таким образом, чтобы любой элемент, который «выглядит» как он, может иметь родительский объект (свойство типа BaseClass) с внешним ключом, я буду сортировать эти элементы в списке и вставлять их последним и, надеюсь, избегать нарушений внешнего ключа.

Но я надеюсь, что есть другие альтернативы.

Кроме того, когда я выполняю восстановление, генератор Id установлен в назначенный, поэтому я не думаю, что моя проблема связана с неизвестными или недопустимыми идентификаторами. В исходных данных мои идентификаторы - это GUID. (Я могу изменить это на hilo integers позже, но по одной проблеме за раз).

Любая помощь будет очень признательна.

Заранее спасибо ...

ответ

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. 
       } 
      } 
Смежные вопросы