As part of learning RavenDB, I am trying to update a collection of stocks based on a list I download nightly.
I have a Stock class where Id is the stock symbol:
public class Stock
{
public string Id { get; set; }
public StockStatus Status { get; set; }
}
I'm trying to sync the list with this algorithm:
- Update or insert all stocks downloaded now as "StillActive".
- Any stocks with the status of "Active" from last time means they weren't in the update and need to be "Deleted".
- All stocks still "StillActive" become the new "Active" stocks.
Here is the implementation:
List<Stock> stocks = DownloadStocks();
using (var session = RavenContext.Store.OpenSession())
{
foreach (Stock stock in stocks)
{
stock.Status = StockStatus.StillActive;
session.Store(stock);
}
session.SaveChanges();
session.PatchUpdateCutoffNow("Stocks/ByStatus", "Status:Active", "Status", StockStatus.Deleted);
session.PatchUpdateCutoffNow("Stocks/ByStatus", "Status:StillActive", "Status", StockStatus.Active);
}
PatchUpdateCutoffNow is an extension method that does an UpdateByIndex with a Cutoff of now:
public static void PatchUpdateCutoffNow(this IDocumentSession session, string indexName, string query, string name, object val)
{
session.Advanced.DatabaseCommands.UpdateByIndex(indexName,
new IndexQuery() { Query = query, Cutoff = DateTime.Now },
new[]
{
new PatchRequest
{
Type = PatchCommandType.Set,
Name = name,
Value = val.ToString()
}
});
}
I end up with a lot of stocks Deleted that shouldn't be. My guess is the SaveChanges is asynchronous and doesn't finish by the time the PatchUpdateCutoffNow starts so I end up with some amount of Stocks with a status of "Deleted" when they should be "Active". I guess the IndexQuery cutoff doesn't apply since the SaveChanges isn't directly against the "Stocks/ByStatus" index.
Is there a way to make SaveChanges synchronous or some other way to do this that fits more with the NoSQL/RavenDB way of thinking?