복붙노트

[MONGODB] MongoDB를 문자열로 열거 형을 저장

MONGODB

MongoDB를 문자열로 열거 형을 저장

문자열 이름이 아닌 서수 값으로 열거 형을 저장하는 방법이 있나요?

예:

나는이 열거있어 상상 :

public enum Gender
{
    Female,
    Male
}

이제 몇 가지 가상 사용자로 존재하는 경우

...
Gender gender = Gender.Male;
...

그것은으로 MongoDB를 데이터베이스에 저장됩니다 {... "성별": 1 ...}

{... "남성"... "성별"}하지만 난 이런 일을 원합니다

이게 가능해? 사용자 정의 매핑, 반사 트릭, 뭐든간에.

내 상황에 맞는 : 나는 POCO (물론, 나는 가끔 액세스 라우터 사용 다형성을 표시)을 통해 강력한 형식의 컬렉션을 사용합니다. 나는 작업 단위의 형태로 얇은 데이터 액세스 추상화 계층을 가지고있다. 내가 직렬화 아니에요 그래서 / 각 개체를 직렬화 복원 그러나 나는 (그리고 할) 일부 ClassMaps을 정의 할 수 있습니다. 나는 공식 MongoDB의 드라이버 + 유창 - MongoDB를 사용합니다.

해결법

  1. ==============================

    1.MongoDB를 .NET 드라이버는 처리하는 방법을 특정 매핑 CLR 유형과 데이터베이스 요소 사이에 결정하는 규칙을 적용 할 수 있습니다.

    MongoDB를 .NET 드라이버는 처리하는 방법을 특정 매핑 CLR 유형과 데이터베이스 요소 사이에 결정하는 규칙을 적용 할 수 있습니다.

    당신이 당신의 열거에 적용 할 경우 모든 유형에 속성을 추가하거나 수동으로 모든 유형의지도에 반대, 당신은 단지 한 번 응용 프로그램 도메인 (일반적으로 응용 프로그램을 시작할 때) 당 규칙을 설정해야합니다 :

    // Set up MongoDB conventions
    var pack = new ConventionPack
    {
        new EnumRepresentationConvention(BsonType.String)
    };
    
    ConventionRegistry.Register("EnumStringConvention", pack, t => true);
    
  2. ==============================

    2.

    using MongoDB.Bson;
    
    using Newtonsoft.Json;
    using Newtonsoft.Json.Converters;
    
    public class Person
    {
        [JsonConverter(typeof(StringEnumConverter))]  // JSON.Net
        [BsonRepresentation(BsonType.String)]         // Mongo
        public Gender Gender { get; set; }
    }
    
  3. ==============================

    3.당신은 열거를 포함하는 클래스의 클래스 맵을 사용자 정의하고 부재는 문자열로 표현되도록 지정할 수 있습니다. 이 직렬화 및 열거 형의 직렬화를 모두 처리합니다.

    당신은 열거를 포함하는 클래스의 클래스 맵을 사용자 정의하고 부재는 문자열로 표현되도록 지정할 수 있습니다. 이 직렬화 및 열거 형의 직렬화를 모두 처리합니다.

    if (!MongoDB.Bson.Serialization.BsonClassMap.IsClassMapRegistered(typeof(Person)))
          {
            MongoDB.Bson.Serialization.BsonClassMap.RegisterClassMap<Person>(cm =>
             {
               cm.AutoMap();
               cm.GetMemberMap(c => c.Gender).SetRepresentation(BsonType.String);
    
             });
          }
    

    나는 아직도 열거 세계적으로 문자열로 표현 될 수 있음을 지정하는 방법을 찾고 있지만, 이것은 내가 현재 사용하고있는 방법이다.

  4. ==============================

    4.MemberSerializationOptionsConvention 사용은 열거가 저장되는 방법에 대한 규칙을 정의합니다.

    MemberSerializationOptionsConvention 사용은 열거가 저장되는 방법에 대한 규칙을 정의합니다.

    new MemberSerializationOptionsConvention(typeof(Gender), new RepresentationSerializationOptions(BsonType.String))
    
  5. ==============================

    5.드라이버 2.X와 나는 특정 시리얼 라이저를 사용하여 해결 :

    드라이버 2.X와 나는 특정 시리얼 라이저를 사용하여 해결 :

    BsonClassMap.RegisterClassMap<Person>(cm =>
                {
                    cm.AutoMap();
                    cm.MapMember(c => c.Gender).SetSerializer(new EnumSerializer<Gender>(BsonType.String));
                });
    
  6. ==============================

    6.난 그냥 리카르도 로드리게스 '대답을 적용하는 MongoDB를에 문자열을 제대로 직렬화 열거 값으로 어떤 경우에는 충분하지 않은 것으로 나타났습니다 :

    난 그냥 리카르도 로드리게스 '대답을 적용하는 MongoDB를에 문자열을 제대로 직렬화 열거 값으로 어떤 경우에는 충분하지 않은 것으로 나타났습니다 :

    // Set up MongoDB conventions
    var pack = new ConventionPack
    {
        new EnumRepresentationConvention(BsonType.String)
    };
    
    ConventionRegistry.Register("EnumStringConvention", pack, t => true);
    

    데이터 구조가 열거 값이 객체로 박스되는 포함하면 MongoDB를 직렬화 직렬화하기 위해 설정 EnumRepresentationConvention를 사용하지 않습니다.

    당신이 MongoDB를 드라이버의 ObjectSerializer의 구현을 보면 실제로, 그것은 (열거 값 INT32) 포장 된 값의 TypeCode를 해결하고 데이터베이스에 열거 값을 저장 유형을 사용합니다. 그래서 박스 열거 값은 INT 값으로 연재되고 결국. 뿐만 아니라 직렬화 복원되는 때 그들은 INT 값으로 유지됩니다.

    이 설정을 변경하기 위해서는 박스 값이 열거 인 경우 설정 EnumRepresentationConvention을 적용하는 사용자 정의 ObjectSerializer 쓰기 가능합니다. 이 같은:

    public class ObjectSerializer : MongoDB.Bson.Serialization.Serializers.ObjectSerializer
    {
         public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
        {
            var bsonWriter = context.Writer;
            if (value != null && value.GetType().IsEnum)
            {
                var conventions = ConventionRegistry.Lookup(value.GetType());
                var enumRepresentationConvention = (EnumRepresentationConvention) conventions.Conventions.FirstOrDefault(convention => convention is EnumRepresentationConvention);
                if (enumRepresentationConvention != null)
                {
                    switch (enumRepresentationConvention.Representation)
                    {
                        case BsonType.String:
                            value = value.ToString();
                            bsonWriter.WriteString(value.ToString());
                            return;
                    }
                }
            }
    
            base.Serialize(context, args, value);
        }
    }
    

    다음 객체 직렬화에 사용하는 것과 같은 사용자 지정 serializer를 설정합니다

    BsonSerializer.RegisterSerializer(typeof(object), new ObjectSerializer());
    

    이렇게하면 박스 열거 값이 바로 언 박싱 된 것과 같은 문자열로 저장됩니다 보장합니다.

    명심 그러나 당신의 문서를 역 직렬화 할 때 박스 값은 문자열 유지됩니다. 그것은 원래 열거 형 값으로 변환 다시되지 않습니다. 원래 열거 값으로 문자열을 다시 변환해야하는 경우, 차별 필드 가능성이 시리얼 라이저가에 desrialize하는 열거 형이 무엇인지 알 수 있도록 문서에 추가해야합니다.

    그것을 할 수있는 한 가지 방법은 차별 필드 (_t)과 값 필드 (_V)이 열거 형과 문자열 값을 저장하는 데 사용되는되는 단지 문자열 대신 bson 문서를 저장하는 것입니다.

  7. ==============================

    7.댓글에 크리스 스미스에 의해 제안 나는 열거 항목에 값을 할당 결국 :

    댓글에 크리스 스미스에 의해 제안 나는 열거 항목에 값을 할당 결국 :

    아니 정확히 내가 찾던하지만 다른 방법의 주위가 없습니다 것 같다.

  8. ==============================

    8.대답은 그러나 사전 작동하지 않습니다, 여기에 게시 TEnum 및 TEnum []을 위해 잘 작동합니다. 코드를 사용하여 시리얼 라이저를 초기화 할 때 당신은 그러나 나는 속성을 통해이 작업을 수행하고 싶었,이를 달성 할 수있다. 나는 키와 값에 대한 시리얼 라이저로 구성 할 수있는 유연한 DictionarySerializer을 만들었습니다.

    대답은 그러나 사전 작동하지 않습니다, 여기에 게시 TEnum 및 TEnum []을 위해 잘 작동합니다. 코드를 사용하여 시리얼 라이저를 초기화 할 때 당신은 그러나 나는 속성을 통해이 작업을 수행하고 싶었,이를 달성 할 수있다. 나는 키와 값에 대한 시리얼 라이저로 구성 할 수있는 유연한 DictionarySerializer을 만들었습니다.

    public class DictionarySerializer<TDictionary, KeySerializer, ValueSerializer> : DictionarySerializerBase<TDictionary>
        where TDictionary : class, IDictionary, new()
        where KeySerializer : IBsonSerializer, new()
        where ValueSerializer : IBsonSerializer, new()
    {
        public DictionarySerializer() : base(DictionaryRepresentation.Document, new KeySerializer(), new ValueSerializer())
        {
        }
    
        protected override TDictionary CreateInstance()
        {
            return new TDictionary();
        }
    }
    
    public class EnumStringSerializer<TEnum> : EnumSerializer<TEnum>
        where TEnum : struct
    {
        public EnumStringSerializer() : base(BsonType.String) { }
    }
    

    키와 값이 모두 열거 타입이지만 시리얼의 조합이 될 수있는 곳이, 같은 사용법 :

        [BsonSerializer(typeof(DictionarySerializer<
            Dictionary<FeatureToggleTypeEnum, LicenseFeatureStateEnum>, 
            EnumStringSerializer<FeatureToggleTypeEnum>,
            EnumStringSerializer<LicenseFeatureStateEnum>>))]
        public Dictionary<FeatureToggleTypeEnum, LicenseFeatureStateEnum> FeatureSettings { get; set; }
    
  9. from https://stackoverflow.com/questions/6996399/storing-enums-as-strings-in-mongodb by cc-by-sa and MIT license