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

如何在C#中为内存对象应用MongoDB风格的更新补丁?

如何将MongoDB风格的更新定义应用到C#内存对象

问题场景

现有C#内存中的Employee对象,通过MongoDB驱动的Builders<Employee>.Update创建了更新定义,生成了类似{ "$set" : { "LastName" : "ln1", "FirstName" : "another" } }的更新指令,但无真实数据库,需要直接将该更新应用到内存对象上。示例代码如下:

using MongoDB.Bson.Serialization;
using MongoDB.Driver;

class Program
{
    class Employee
    {
        public string LastName { get; set; } = string.Empty;
        public string FirstName { get; set; } = string.Empty;
    }
    public static void Main(string[] args)
    {
        Employee employee = new Employee()
        {
            LastName = "ln",
            FirstName = "test"
        };

        var def = Builders<Employee>.Update.Set("LastName", "ln1");
        def = def.Set("FirstName", "another");
        var registry = BsonSerializer.SerializerRegistry;
        var serializer = registry.GetSerializer<Employee>();
        var patch = def?.Render(serializer, registry).ToString() ?? string.Empty;
        //TODO: 如何将此“补丁”应用到employee对象?
    }
}

解决方案

MongoDB .NET驱动未直接提供内存对象更新API,但可通过以下两种方式实现需求:

方法一:基于BsonDocument序列化/反序列化(推荐)

借助MongoDB的Bson序列化机制,将对象转为BsonDocument后应用更新,再转回原类型,支持所有MongoDB更新操作符:

// 将内存对象转为BsonDocument
var employeeBson = employee.ToBsonDocument();
// 渲染更新定义为可执行的BsonDocument
var updateBson = def.Render(serializer, registry);
// 应用更新到BsonDocument
employeeBson.ApplyUpdate(updateBson);
// 将更新后的BsonDocument转回Employee对象
employee = employeeBson.ToObject<Employee>();

方法二:反射手动解析(适合简单场景)

若仅需处理$set操作,可通过反射遍历更新字段并设置对象属性:

// 提取更新定义中的$set部分
var setUpdate = updateBson["$set"].AsBsonDocument;
foreach (var element in setUpdate)
{
    // 获取对象对应的属性
    var property = typeof(Employee).GetProperty(element.Name);
    if (property != null)
    {
        // 将Bson值转换为属性类型并赋值
        var value = element.Value.ToType(property.PropertyType);
        property.SetValue(employee, value);
    }
}

完整可运行示例

using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Driver;
using System.Reflection;

class Program
{
    class Employee
    {
        public string LastName { get; set; } = string.Empty;
        public string FirstName { get; set; } = string.Empty;
    }
    public static void Main(string[] args)
    {
        Employee employee = new Employee()
        {
            LastName = "ln",
            FirstName = "test"
        };

        var def = Builders<Employee>.Update.Set("LastName", "ln1");
        def = def.Set("FirstName", "another");
        var registry = BsonSerializer.SerializerRegistry;
        var serializer = registry.GetSerializer<Employee>();
        var updateBson = def.Render(serializer, registry);

        // 方法一测试
        var employeeBson = employee.ToBsonDocument();
        employeeBson.ApplyUpdate(updateBson);
        employee = employeeBson.ToObject<Employee>();
        Console.WriteLine($"方法一结果:LastName={employee.LastName}, FirstName={employee.FirstName}");

        // 重置对象测试方法二
        employee = new Employee() { LastName = "ln", FirstName = "test" };
        var setUpdate = updateBson["$set"].AsBsonDocument;
        foreach (var element in setUpdate)
        {
            var property = typeof(Employee).GetProperty(element.Name);
            if (property != null)
            {
                var value = element.Value.ToType(property.PropertyType);
                property.SetValue(employee, value);
            }
        }
        Console.WriteLine($"方法二结果:LastName={employee.LastName}, FirstName={employee.FirstName}");
    }
}

注意事项

  • 方法一兼容性更强,支持$inc、$push等所有MongoDB更新操作符;
  • 方法二仅针对$set操作,如需支持其他操作符,需自行扩展解析逻辑。

内容的提问来源于stack exchange,提问作者No Name

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 04:10:05