在 MongoDB 的文档中更改存储为字符串的枚举值

Changing an enum value stored as a string inside a document in MongoDB

我有一个 class,里面有一个枚举 属性。由于下面文档的 .NET 表示中的属性,属性 在保存整个文档时作为字符串写入数据库

public enum Status { Good, Bad }

public class Document
{
    [BsonRepresentation(BsonType.String)]
    public Status Status { get; set; }
    // ...
}

稍后当我想更新文档中的值而不保存整个文档时,我构建了一个这样的过滤器:

var builder = Builders<T>.Update;
var filter = builder.Set(new StringFieldDefinition<T, Status>(fieldName), (Status)value);
var result = await Context.Collection.UpdateManyAsync(filter, update);

不幸的是,这写入了枚举的整数值。

如果我将过滤器更改为此

var filter = builder.Set(new StringFieldDefinition<T, Status>(fieldName), value.ToString());

driver 将抛出一个 InvalidCastException。如何正确构建过滤器?有没有其他方法可以不替换文档直接设置枚举值?

我想到可能有一种方法可以将 single-field 行为关联回整个文档的属性,但我似乎无法找到如何做到这一点。

这个怎么样:(未测试)

await collection.UpdateManyAsync(
    Builders<BsonDocument>.Filter.Eq(fieldName, (Status)value)), //filter definition
    Builders<BsonDocument>.Update.Set(fieldName, (Status)value));

C# 枚举由整数表示。默认情况下,第一个枚举为 0,第二个为 1,依此类推。您可以将特定的整数值分配给枚举条目,但它们同样被解释为整数,而不是字符串。要获取与您的枚举条目匹配的字符串值,您必须使用 enum.parse 方法。

我目前没有可用的 C# 环境,所以我无法测试我的建议,但请试试这个...

var filter = builder.Set(new StringFieldDefinition<T, String>(fieldName), Enum.Parse(typeof(Status), value));

[BsonRepresentation(BsonType.String)] 修饰枚举 属性 后,您无需在代码中进行任何转换。该属性指示驱动程序将枚举值的名称存储在数据库中,并在反序列化时将其设置回适当的枚举值。所以您的应用程序代码只能处理枚举。

    var statusValue = Status.Good;

    var filter = Builders<Document>.Filter.Eq(d => d.Status, Status.Bad);
    var update = Builders<Document>.Update.Set(d => d.Status, statusValue);

    collection.UpdateMany(filter, update);

测试程序:

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Entities;
using MongoDB.Entities.Core;

namespace Whosebug
{
    public enum Status { Good, Bad }

    public class Document : Entity
    {
        [BsonRepresentation(BsonType.String)]
        public Status Status { get; set; }
    }

    public static class Program
    {
        private static void Main()
        {
            new DB("test");

            new Document { Status = Status.Bad }.Save();

            var statusValue = Status.Good;

            DB.Update<Document>()
              .Match(f => f.Eq(d => d.Status, Status.Bad))
              .Modify(b => b.Set(d => d.Status, statusValue))
              .Execute();
        }
    }
}