【问题标题】:Changing an enum value stored as a string inside a document in MongoDB更改存储为 MongoDB 文档中的字符串的枚举值
【发布时间】:2020-02-06 21:13:21
【问题描述】:

我有一个类,里面有一个枚举属性。保存整个文档时,该属性作为字符串写入数据库,因为下面文档的 .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());

驱动程序将抛出一个InvalidCastException。如何正确构建过滤器?有没有另一种方法可以直接设置枚举值而不替换文档?

我想到可能有一种方法可以将单字段行为与整个文档的属性相关联,但我似乎不知道如何做到这一点。

【问题讨论】:

    标签: c# mongodb enums mongodb-.net-driver


    【解决方案1】:

    一旦你用[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 StackOverFlow
    {
        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();
            }
        }
    }

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        【解决方案3】:

        这个怎么样:(未测试)

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-06-19
          • 2018-05-23
          • 1970-01-01
          • 1970-01-01
          • 2012-09-05
          • 1970-01-01
          相关资源
          最近更新 更多