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

如何在MongoDB C#驱动中不使用eval实现自增字段?

在MongoDB C#驱动中实现自增字段(替代已弃用的Eval)

嘿,我来帮你搞定这个问题!既然Eval已经被MongoDB弃用了,咱们可以用原子性的FindOneAndUpdate操作来实现自增序列功能——这也是官方推荐的替代方案,既安全又能保证并发场景下不会出现重复ID。

第一步:准备序列集合

首先,你需要一个专门存储序列的集合(比如叫counters),每个文档对应一个序列的当前值,结构大概是这样:

{
  "_id": "productid",
  "sequence_value": 0
}

如果这个集合还没有,你可以在C#里初始化,或者直接在Mongo控制台创建。

第二步:实现获取自增ID的方法

在C#里,我们可以通过FindOneAndUpdateAsync来原子性地递增序列值并返回最新值。先定义一个对应counters集合的实体类:

public class Counter
{
    public ObjectId Id { get; set; }
    public string SequenceName { get; set; } // 对应控制台里的"productid"
    public int SequenceValue { get; set; }
}

然后写一个获取下一个序列值的方法:

public async Task<int> GetNextSequenceValueAsync(IMongoDatabase database, string sequenceName)
{
    var countersCollection = database.GetCollection<Counter>("counters");
    
    // 定义更新操作:递增sequence_value字段
    var update = Builders<Counter>.Update.Increment(c => c.SequenceValue, 1);
    
    // 执行原子操作:找到对应序列,更新并返回更新后的文档
    var result = await countersCollection.FindOneAndUpdateAsync(
        filter: c => c.SequenceName == sequenceName,
        update: update,
        options: new FindOneAndUpdateOptions<Counter>
        {
            IsUpsert = true, // 如果序列不存在,自动创建
            ReturnDocument = ReturnDocument.After // 返回更新后的文档(包含最新的sequence_value)
        });
    
    // 如果是刚创建的新序列,返回1(因为初始值是0,递增后是1)
    return result?.SequenceValue ?? 1;
}

第三步:插入文档时使用自增ID

现在你可以在插入产品的时候,先调用上面的方法获取自增ID,再执行插入操作:

public async Task InsertProductAsync(IMongoDatabase database)
{
    var productsCollection = database.GetCollection<BsonDocument>("products");
    
    // 获取下一个productid的自增值
    var nextProductId = await GetNextSequenceValueAsync(database, "productid");
    
    // 构造产品文档
    var product = new BsonDocument
    {
        { "_id", nextProductId },
        { "product_name", "Apple iPhone" },
        { "category", "mobiles" }
    };
    
    await productsCollection.InsertOneAsync(product);
}

为什么这个方案靠谱?

  • 原子性:FindOneAndUpdate是原子操作,即使多个请求同时调用,也不会出现重复的ID。
  • 替代Eval:完全避开了已弃用的Eval,符合MongoDB的最佳实践。
  • 灵活性:可以给不同的业务对象(比如订单、用户)创建不同的序列,只需要传入不同的sequenceName即可。

内容的提问来源于stack exchange,提问作者André Pontes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:14:22