Изменение значения перечисления, хранящегося в виде строки внутри документа в MongoDB - PullRequest
2 голосов
/ 07 февраля 2020

У меня есть класс, у которого есть свойство enum. Свойство записывается в виде строки в базу данных при сохранении всего документа из-за атрибута в представлении. 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. Как правильно построить фильтр? Есть ли другой способ установить значение перечисления напрямую, без замены документа?

Мне пришло в голову, что может быть способ связать поведение одного поля с атрибутом во всем документе, но я могу кажется, не выяснил, как это сделать.

Ответы [ 3 ]

0 голосов
/ 07 февраля 2020

C# перечисления представлены целыми числами. По умолчанию первое перечисление равно 0, а второе - 1 и т. Д. Вы можете назначить указанные c целочисленные значения элементам перечисления, но опять-таки они интерпретируются как целые числа, а не строки. Чтобы получить строковое значение, соответствующее вашей записи enum, вы должны использовать метод enum.parse.

В настоящее время у меня нет среды C#, поэтому я не могу проверить свое предложение, но, пожалуйста, попробуйте это ...

var filter = builder.Set(new StringFieldDefinition<T, String>(fieldName), Enum.Parse(typeof(Status), value));
0 голосов
/ 07 февраля 2020

после того, как вы украсили свойство enum с помощью [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();
        }
    }
}
0 голосов
/ 07 февраля 2020

Как насчет этого: (не проверено)

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