![](/img/trans.png)
[英]MongoDB C# 2.1 ReplaceOneAsync not working for repository pattern
[英]ReplaceOneAsync() immediately after InsertOneAsync() not always working, even when journaled
在单实例MongoDB服务器上,即使将客户端的写操作设置为日志记录,插入后也无法立即替换每千两千个文档中的一个。
我的印象是,一旦记录日志,便可以立即使用这些文档进行查询。
下面的代码插入一个文档,然后更新该文档的DateModified
属性,并尝试根据该文档的ID和该属性的旧值来更新该文档。
public class MyDocument
{
public BsonObjectId Id { get; set; }
public DateTime DateModified { get; set; }
}
static void Main(string[] args)
{
var r = Task.Run(MainAsync);
Console.WriteLine("Inserting documents... Press any key to exit.");
Console.ReadKey(intercept: true);
}
private static async Task MainAsync()
{
var client = new MongoClient("mongodb://localhost:27017");
var database = client.GetDatabase("updateInsertedDocuments");
var concern = new WriteConcern(journal: true);
var collection = database.GetCollection<MyDocument>("docs").WithWriteConcern(concern);
int errorCount = 0;
int totalCount = 0;
do
{
totalCount++;
// Create and insert the document
var document = new MyDocument
{
DateModified = DateTime.Now,
};
await collection.InsertOneAsync(document);
// Save and update the modified date
var oldDateModified = document.DateModified;
document.DateModified = DateTime.Now;
// Try to update the document by Id and the earlier DateModified
var result = await collection.ReplaceOneAsync(d => d.Id == document.Id && d.DateModified == oldDateModified, document);
if (result.ModifiedCount == 0)
{
Console.WriteLine($"Error {++errorCount}/{totalCount}: doc {document.Id} did not have DateModified {oldDateModified.ToString("yyyy-MM-dd HH:mm:ss.ffffff")}");
await DoesItExist(collection, document, oldDateModified);
}
}
while (true);
}
该代码以每秒约250个文档的速度插入。 在1,000至15,000个调用ReplaceOneAsync(d => d.Id == document.Id && d.DateModified == oldDateModified, ...)
失败,因为它返回的ModifiedCount
为0。失败率取决于我们是否运行Debug或Release版本并且是否连接调试器:提高速度意味着出现更多错误。
显示的代码代表我无法轻易更改的内容。 当然,我宁愿执行一系列Update.Set()
调用,但是现在这实际上不是一个选择。 某种存储库模式抽象了InsertOneAsync()
ReplaceOneAsync()
后的ReplaceOneAsync()
,该存储库模式通过引用来更新实体。 方法的非异步副本显示相同的行为。
在插入和替换之间使用简单的Thread.Sleep(100)
缓解此问题。
当查询失败时,我们会稍等片刻,然后尝试在下面的代码中再次查询该文档,每次都会找到它。
private static async Task DoesItExist(IMongoCollection<MyDocument> collection, MyDocument document, DateTime oldDateModified)
{
Thread.Sleep(500);
var fromDatabaseCursor = await collection.FindAsync(d => d.Id == document.Id && d.DateModified == oldDateModified);
var fromDatabaseDoc = await fromDatabaseCursor.FirstOrDefaultAsync();
if (fromDatabaseDoc != null)
{
Console.WriteLine("But it was found!");
}
else
{
Console.WriteLine("And wasn't found!");
}
}
发生这种情况的版本:
这是MongoDB中的问题,还是我们做(或假设)做错了事?
或者,实际的最终目标是如何确保更新可以立即检索插入内容?
如果新文档与旧文档相同,则ReplaceOneAsync返回0(因为未进行任何更改)。
在我看来,如果您的测试执行得足够快,则对DateTime.Now的各种调用可能会返回相同的值,因此您可能会将完全相同的文档传递给InsertOneAsync和ReplaceOneAsync。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.