Я использую RavenDB для хранения нескольких тысяч документов. Данные поступают из ежедневной XML-ленты, которую я буду обновлять, запустив консольное приложение C#. Ниже приведен код, который обрабатывает фид, чтобы синхронизировать базу данных с любыми изменениями. У меня было немало проблем с этим, поэтому мне интересно, выбрал ли я неправильную стратегию. Вот несколько важных замечаний.Как мне обновить несколько документов RavenDB из ежедневного фида?
- Новые элементы могут быть добавлены к сырью и существующие элементы могут изменились, поэтому каждый раз, когда он работает, я хочу добавить или обновить документ в зависимости от того, это или нет новый.
- Корзина xml не содержит ссылок на мои идентификаторы RavenDB, только ее внутренний ключ для каждого элемента. Поэтому при получении существующего документа для обновления я могу сделать это только путем изучения свойства «SourceID» в документе.
- Я использую «брать», чтобы работать только с 500 документами, частично из-за того, что мой db ограничен 1000 документами, а отчасти потому, что без Take() Кажется, я могу получить только 128 документов.
- Как указано выше, этот код падает с ошибкой «не может сделать более 30 обновлений в сеансе», я думаю, потому что каждый раз, когда я пытаюсь выполнить , вы можете получить существующую запись из dbItems, которая на самом деле попадает в базу данных снова ,
- Я могу исправить проблему в (4) выше, вызвав ToList() на элементах, но если я сделаю это, то существующий элемент не будет обновляться, когда я вызываю session.SaveChanges() (Я представляю это как a отключен recordset).
Может ли кто-нибудь дать мне несколько указателей?
public void ProcessFeed(string rawXml)
{
XDocument doc = XDocument.Parse(rawXml);
var items = ExtractItemsFromFeed(doc).OrderBy(x => x.SourceId).Take(500);
using (IDocumentSession session = _store.OpenSession())
{
var dbItems = session.Query<AccItem>().OrderBy(x => x.SourceId).Take(500);
foreach (var item in items)
{
var existingRecord = dbItems.SingleOrDefault(x => x.SourceId == item.SourceId);
if (existingRecord == null)
{
session.Store(item);
_logger.Info("Saved new item {0}.", item.ShortName);
}
else
{
// update just one field for now
existingRecord.Village = item.Village;
_logger.Info("Updated item {0}.", item.ShortName);
}
}
session.SaveChanges();
}
}
В (4) вы пишете «не может делать более 30 обновлений в сеансе». Насколько я понимаю, записи переносятся, и поскольку вы только вызываете SaveChanges один раз за сеанс, так что это должно привести только к одному запросу на сервер для записи: https://ravendb.net/docs/theory/safe-by-default –
Это именно то, что я думал, и это сделало результаты, которые я видел сбивчивыми. Однако я думаю, что это чтение, а не записи в этом случае, которые вызывают проблему (см. Ответ ниже). – centralscru