Я играл с LiteDb, чтобы улучшить производительность моего фида данных.Фид работает в базе данных Azure, и чтобы уменьшить количество используемых DTU и соединений (я делаю некоторую логику в параллельном цикле поиска), я извлекаю данные из базы данных, помещаю их в индекс LiteDb, а затем запускаюмоя логика вокруг этого.Большинство моих сценариев работают отлично.Сначала я делаю массовое добавление индексов, а затем заново открываю litdb в режиме только для чтения и выполняю свои запросы. Примерно так:
using (var db = new LiteDatabase("SiloLite.db"))
{
db.DropCollection("SiloProduct");
var products = db.GetCollection<SiloProduct>("SiloProduct");
products.InsertBulk(_siloproductRepository.Table.ToList());
products.EnsureIndex(x => x.Sku);
db.Engine.EnsureIndex("SiloProduct", "UniqueProdId", "$.Sku+';'+$.ParentProductId", true);
}
using (var db = new LiteDatabase($"Filename={AppDomain.CurrentDomain.BaseDirectory}\\SiloLite.db;mode=ReadOnly"))
{
var products = db.GetCollection<SiloProduct>("SiloProduct");
var manufacturers = db.GetCollection<SiloManufacturer>("SiloManufacturer");
var productspecificationmap =
db.GetCollection<SiloProductSpecificationAttributeMapping>(
"SiloProductSpecificationAttributeMapping");
var specificationAttributes =
db.GetCollection<SiloSpecificationAttribute>("SiloSpecificationAttribute");
var specificationAttributeOptions =
db.GetCollection<SiloSpecificationAttributeOption>("SiloSpecificationAttributeOption");
Parallel.ForEach(katartlist, KatartItem =>
{
SaveData(KatartItem, specificationAttributes, specificationAttributeOptions, productspecificationmap,
manufacturers, products);
});
_logger.Information("Completed updating Product Specifications");
}
И он прекрасно работает во всех сценариях, кроме одного.Если я попытаюсь выполнить запрос, а затем попытаться сохранить эти данные в другой коллекции LiteDb жалуется.Это то, что я пытаюсь сделать
var currentspecOptCollection = new List<SiloProductSpecificationAttributeMapping>(liteProdSpecCollection.Find(x => x.ProductId.Equals(productId)).ToList());
var specstoDelete = currentspecOptCollection
.Where(x => !specificationattributeoptionlist.Contains(x.SpecificationAttributeOptionId))
.ToList();
if (specstoDelete.Any())
{
foreach (var specattr in specstoDelete)
{
_specattrDeleteList.Add(specattr);
}
}
Эта логика выполняется внутри Parallel.Foreach и LiteDb выдает эту ошибку
System.InvalidOperationException: Operations that change non-concurrent collections must have exclusive access. A concurrent update was performed on this collection and corrupted its state. The collection's state is no longer correct.
at System.Collections.Generic.Dictionary`2.FindEntry(TKey key)
at System.Collections.Generic.Dictionary`2.TryGetValue(TKey key, TValue& value)
at LiteDB.CacheService.GetPage(UInt32 pageID)
at LiteDB.PageService.GetPage[T](UInt32 pageID)
at LiteDB.QueryCursor.Fetch(TransactionService trans, DataService data, BsonReader bsonReader)
at LiteDB.LiteEngine.Find(String collection, Query query, Int32 skip, Int32 limit)+MoveNext()
at LiteDB.LiteEngine.Find(String collection, Query query, String[] includes, Int32 skip, Int32 limit)+MoveNext()
at LiteDB.LiteCollection`1.Find(Query query, Int32 skip, Int32 limit)+MoveNext()
at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Boolean& found)
at CreateOrUpdateProductSpecifications(KatartItem katartItem, VarData vd, SiloManufacturer manufacturer, SiloProduct product, LiteCollection`1 liteSpecCollection, LiteCollection`1 liteSpecOptCollection, LiteCollection`1 liteProdSpecCollection) in *** 1399
Не уверен, что я делаю здесь неправильно. Любые указатели помогут