You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的修改校验。你的原代码执行逻辑:

  1. 检查是否存在匹配_id=batch.Id的文档;
  2. 不存在时,先创建一个带指定_id的空文档;
  3. 用batch对象全量替换这个新文档。

即使batch.Id与filter中的_id值完全相同,MongoDB仍会将全量替换判定为"修改_id字段"操作,而_id作为不可变字段会被拒绝,最终抛出异常。

内容的提问来源于stack exchange,提问作者Age of Empires

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 17:49:50