我想问你是否会在一个原子操作中执行以下代码。我正在使用mongodb c#driver。
方法的输入是我想要更新的对象的id列表。
public void Update(IEnumerable<string> ids)
{
var query = Query<T>.Where(t => ids.Contains(t.Id));
var update = Update.Set("Modified", DateTime.Now); //this is just example of update
var options = new MongoUpdateOptions {Flags = UpdateFlags.Multi};
Collection.Update(query, update, options);
}
当我有数百万份文件需要更新时,我很有兴趣。如果在此更新期间出现故障(电源或硬件问题),会发生什么?数据库是否处于一致状态?
感谢。
答案 0 :(得分:0)
MongoDB不支持事务或原子多文档。 MongoDB仅对一个文档执行原子操作。
您可以在the documentation of Mongodb
中查看此内容因此,如果您在此操作期间使用查询更新1000个文档并且服务器崩溃,则某些文档可能会更新,而其他文档则不会更新。
答案 1 :(得分:0)
MongoDB> = 4.0 C#驱动程序> = 2.7 我是怎么做到的...
转到“示例代码”
在我可以访问我的客户端(IMongoClient)的DbContext类中,我定义了会话:
public IClientSessionHandle StartSession()
{
return _client.StartSession(new ClientSessionOptions());
}
public async Task<IClientSessionHandle> StartSessionAsync()
{
return await _client.StartSessionAsync(new ClientSessionOptions());
}
正如文档所述,如果仅这些事务接连进行,它们便能够一次又一次地执行多个事务
会话用于将一系列操作分组在一起 彼此相关,应该在同一会话中执行 选项。会话也用于交易。
这些会议说,应在您结束操作后立即关闭它们。
所以您实际上应该像下面这样编写它,或者根据您的情况执行手动处理:
// db is what i named my context, where i defined all my collections and database related stuffs.
// if you have direct access to client, you can call `StartSession/Async` exactly over the `client` object
using(var session = _db.StartSessionAsync()) {
//... All transactional code will go here
}
// Here, on ending the block, Will automatically call `Dispose` method, and the object will no longer exists
在session
对象上
使用以下方法启动,落实或中止交易 IClientSession。一个会话一次只能执行一个事务, 但是一个会话可以执行多个事务,只要每个事务 事务在下一个事务开始之前已提交或中止。
在此步骤中,您需要先启动事务,然后才能对数据库进行实际更改...
session.StartTransaction();
会话开始后,您应该执行交易,并在最后...
如果处理成功,则应致电:
session.CommitTransaction();
否则,您需要回滚
session.AbortTransaction();
如您所见,我在mongodb上有两个写操作,另一个对我来说很关键的外部过程,我需要将这三个一起执行,..前两个由事务管理,并且只要第三个不会引发异常,数据库应保持其新状态。
bool error;
using (var session = await _db.StartSessionAsync())
{
session.StartTransaction();
try
{
var deletedImage = _db.GetUserStore<ApplicationUser>().CollectionInstance.UpdateOneAsync(
Builders<ApplicationUser>.Filter.Where(w => w.Id == userId),
Builders<ApplicationUser>.Update.Pull(x => x.ProfilePictures, photoFromRepo));
await _db.ProfilePicture().DeleteAsync(new ObjectId(photoFromRepo.ImageId));
if (photoFromRepo.CloudinaryPublicId != null)
{
var deleteParams = new DeletionParams(photoFromRepo.CloudinaryPublicId);
var result = _cloudinary.Destroy(deleteParams);
if (result.Result == "ok")
{
// ignore
}
else
{
throw new Exception("Cannot delete file from cloud service...");
}
}
await session.CommitTransactionAsync();
error = false;
}
catch (Exception ex)
{
await session.AbortTransactionAsync();
error = true;
}
}
这有效吗?它支持多个集合吗?只有上帝知道,我是根据文档和今天早些时候在回家的路上看到的一些示例编写的,以及我认为可能是正确和可能的...
有些选项可以传递会话,其中一个选项控制读/写问题,另一个选项控制在执行事务之前应尽早处理多少数据(这是什么意思?我自己没有得到,如果您理解,请编辑我的帖子)
public class ClientSessionOptions
{
public bool? CausalConsistency { get; set; }
public TransactionOptions DefaultTransactionOptions { get; set; }
}
public class TransactionOptions
{
public ReadConcern ReadConcern { get; };
public ReadPreference ReadPreference { get; };
public WriteConcern WriteConcern { get; };
public TransactionOptions(
Optional<ReadConcern> readConcern = default(Optional<ReadConcern>),
Optional<ReadPreference> readPreference = default(Optional<ReadPreference>),
Optional<WriteConcern> writeConcern = default(Optional<WriteConcern>));
public TransactionOptions With(
Optional<ReadConcern> readConcern = default(Optional<ReadConcern>),
Optional<ReadPreference> readPreference = default(Optional<ReadPreference>),
Optional<WriteConcern> writeConcern = default(Optional<WriteConcern>))
}