我正在使用RavenDB来保存数千个文档。数据来自每日xml feed,我将通过运行C#控制台应用程序来更新。下面是处理订阅源以使数据库与任何更改保持同步的代码。我遇到了很多问题,所以我想知道我是否采取了错误的策略。以下是一些需要注意的重要事项。
任何人都可以给我一些指示吗?
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();
}
}
答案 0 :(得分:0)
以下是我最终得到的代码。我认为原始版本的最初问题只是我试图为每个项目使用相同的会话,打破30限制。
通过TekPub屏幕录像中的屏幕上的一些代码提示我通过将整个过程批量处理成15组来修复此问题(允许一次读取和一次写入,因此每批次总共30次请求)。这很慢,但并不像我预期的那么慢。我希望一次可能有10,000条记录,所以我只是把它留下来,直到它完成为止。
public void ProcessFeed(string rawXml)
{
XDocument doc = XDocument.Parse(rawXml);
var items = ExtractItemsFromFeed(doc).OrderBy(x => x.SourceId);
int numberOfItems = items.Count;
int batchSize = 15;
int numberOfBatchesRequired = numberOfItems / batchSize;
int numberOfBatchesProcessed = 0;
int numberOfItemsInLastBatch = numberOfItems - (numberOfBatchesRequired * batchSize);
for (var i = 0;i <= numberOfBatchesRequired;i++)
{
using (IDocumentSession session = _store.OpenSession())
{
var numberOfItemsProcessedSoFar = numberOfBatchesProcessed * batchSize;
var numberOfItemsRemaining = numberOfItems - numberOfItemsProcessedSoFar;
int itemsToTake = 15;
if (numberOfItemsRemaining > 0 && numberOfItemsRemaining < 15)
itemsToTake = numberOfItemsRemaining;
foreach (var item in items.Skip(numberOfItemsProcessedSoFar).Take(itemsToTake))
{
var existingRecords = session.Query<AccItem>().Where(x => x.SourceId == item.SourceId).ToList();
if (!existingRecords.Any())
{
session.Store(item);
_logger.Info("Saved new item {0}.", item.ShortName);
}
else
{
if (existingRecords.Count() > 1)
_logger.Warn("There's more than one item in the database with the sourceid {0}", item.SourceId);
existingRecords.First().Village = item.Village;
_logger.Info("Updated item {0}.", item.ShortName);
}
session.SaveChanges();
}
}
numberOfBatchesProcessed++;
}
}