MongoDB C#实现存在更新/不存在插入时的_id报错问题
MongoDB ReplaceOne Upsert报错:_id字段被修改(错误码66)
解决方案1:使用UpdateOne而非ReplaceOne(推荐)
ReplaceOne在upsert场景下的全量替换逻辑会触发MongoDB对_id不可变字段的校验,改用UpdateOne设置所有非_id字段即可避免该问题:
public void CreateOrUpdate(Batch batch) { var filter = Builders<Batch>.Filter.Eq(x => x.Id, batch.Id); var update = Builders<Batch>.Update .Set(x => x.Description, batch.Description) .Set(x => x.AccountId, batch.AccountId) .Set(x => x.BatchName, batch.BatchName); var options = new UpdateOptions { IsUpsert = true }; _batchCollection.UpdateOne(filter, update, options); }
解决方案2:调整ReplaceOne的替换文档,移除_id字段
若坚持使用ReplaceOne,可将对象序列化为BsonDocument后移除_id字段,让MongoDB自动用filter中的_id作为新文档的主键:
public void CreateOrUpdate(Batch batch) { var filter = Builders<Batch>.Filter.Eq(x => x.Id, batch.Id); var options = new ReplaceOptions { IsUpsert = true }; var replacement = batch.ToBsonDocument(); replacement.Remove("_id"); _batchCollection.ReplaceOne(filter, replacement, options); }
错误原因说明
错误码66对应MongoDB对不可变字段_id的修改校验。你的原代码执行逻辑:
- 检查是否存在匹配
_id=batch.Id的文档; - 不存在时,先创建一个带指定_id的空文档;
- 用
batch对象全量替换这个新文档。
即使batch.Id与filter中的_id值完全相同,MongoDB仍会将全量替换判定为"修改_id字段"操作,而_id作为不可变字段会被拒绝,最终抛出异常。
内容的提问来源于stack exchange,提问作者Age of Empires
相关产品推荐
相关产品推荐

