在 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();
}
}
}
我有一个 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();
}
}
}