RavenDB: Asynchronous SaveChanges affecting later updates?
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?
The documents are stored right away, but the patch commands work on an index which has not updated yet. Maybe this helps, inserted between SaveChanges()
and the patching:
using (var s = RavenContext.Store.OpenSession()) {
s
.Query<Stock>("Stocks/ByStatus")
.Customize(c => c.WaitForNonStaleResultsAsOfNow())
.Take(0)
.ToArray();
}
By the way, you don't need a session for DatabaseCommands, you can call them directly on the store.
精彩评论