MongoDB에서 Enum을 많이로 저장
열거 된 이름으로 저장하는 방법이 있습니까?
예 :
이 열거 형이 존재하는 상상해.
public enum Gender
{
Female,
Male
}
이제 가상의 사용자가
...
Gender gender = Gender.Male;
...
MongoDb 데이터베이스에 {... "Gender": 1 ...}로 저장됩니다.
하지만 나는 {... "Gender": "Male"...} 같은 것을 선호합니다.
이것이 가능한가? 커스텀 매핑, 리플렉션 트릭 등.
내 맥락 : POCO보다 강력한 형식의 컬렉션을 사용합니다 (음, AR을 표시하고 다형성을 사용합니다). 작업 단위의 형태로 다양 데이터 액세스 추상화 계층이 있습니다. 그래서 어떤 클래스 맵을 정의 할 수 있습니다. 나는 공식 MongoDb 드라이버 + 유창한 mongodb를 사용합니다.
MongoDB .NET 드라이버를 사용하면 규칙 을 적용 하여 CLR 유형과 데이터베이스 요소의 특정 매핑이 처리 되는 방식 을 사용할 수 있습니다 .
모든 열거 형에 적용되는 모든 유형에 속성을 추가하거나 모든 유형을 수동으로 매핑하는 것과 동일하게 AppDomain 당 한 번에 매핑하는 규칙을 설정합니다 (일반적으로 애플리케이션을 시작할 때).
// Set up MongoDB conventions
var pack = new ConventionPack
{
new EnumRepresentationConvention(BsonType.String)
};
ConventionRegistry.Register("EnumStringConvention", pack, t => true);
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; }
}
열거를 포함하는 클래스에 대한 클래스 맵을 사용자 정의하고 멤버가 맵시있게 표시 할 수 있습니다. 여기 열거 형의 생성 화 및 역 생성 화를 모두 처리합니다.
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);
});
}
열거 된 표현이 전역 언어 표현 표현 지정하는 방법입니다.
MemberSerializationOptionsConvention 을 사용 하여 열거 형 저장 방법에 대한 규칙을 정의합니다.
new MemberSerializationOptionsConvention(typeof(Gender), new RepresentationSerializationOptions(BsonType.String))
드라이버 2.x에서는 여기서 변환기를 사용하여 해결했습니다 .
BsonClassMap.RegisterClassMap<Person>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Gender).SetSerializer(new EnumSerializer<Gender>(BsonType.String));
});
Ricardo Rodriguez의 답변을 적용하는 것만으로 는 일부 경우에 열거 형 값을 MongoDb에 어디에나 거기에서 발견 한 데 충분하지 않습니다.
// Set up MongoDB conventions
var pack = new ConventionPack
{
new EnumRepresentationConvention(BsonType.String)
};
ConventionRegistry.Register("EnumStringConvention", pack, t => true);
데이터 구조에 열거 형 값이 개체 에 포함되는 경우 MongoDB의는 집합 직렬화 EnumRepresentationConvention
을 사용하여 직렬화하지 않습니다 .
당신이 MongoDB를 드라이버의 구현을 보면, ObjectSerializer , 그것은 해결됩니다 TypeCode
(박스형 값의 Int32
열거 값을), 데이터베이스에 열거 된 값을 저장 유형을 사용합니다. 따라서 박스형 열거 형 값은 int
값으로 변환 됩니다. int
역내 화 될 때도 값으로 유지 됩니다.
이를 변경하려면 boxed 값이 열거 형인 경우 ObjectSerializer
집합을 적용 하는 사용자 지정을 작성할 수 있습니다 EnumRepresentationConvention
. 이 같은:
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());
이렇게하면 boxed enum 값이 unboxed 값과 마찬가지로 문자열로 저장됩니다.
그러나 문서를 deserialize 할 때 boxed 값은 문자열로 유지됩니다. 원래 열거 형 값으로 다시 변환되지 않습니다. 문자열을 원래 열거 형 값으로 다시 변환해야하는 경우 serializer가 desrialize 할 열거 형 유형을 알 수 있도록 식별 필드를 문서에 추가해야 할 수 있습니다.
이를 수행하는 한 가지 방법은 문자열 대신 bson 문서를 저장하는 것입니다. 여기에는 식별 필드 ( _t
)와 값 필드 ( _v
)가 열거 형 유형과 문자열 값을 저장하는 데 사용됩니다.
Chris Smith가 주석에서 제안한대로 열거 형 항목에 값을 할당했습니다.
나는 그것을 피할 것입니다. 문자열 값은 정수보다 더 많은 공간을 차지합니다. 지속성이 열거의 각 항목에 관여주고 결정 값을 경우 나는 그러나, 그래서 것
Female = 1
,Male = 2
그렇다면 열거는 문제와 끝까지하지 않도록 변경 이후 또는 항목의 순서에 추가됩니다.
정확히 내가 찾던 것은 아니지만 다른 방법이없는 것 같습니다.
여기에 게시 된 답변은 TEnum
및 TEnum[]
에서는 잘 작동하지만에서는 작동하지 않습니다 Dictionary<TEnum, object>
. 코드를 사용하여 serializer를 초기화 할 때이 작업을 수행 할 수 있지만 속성을 통해이 작업을 수행하고 싶었습니다. 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) { }
}
키와 값이 모두 열거 형이지만 serializer의 모든 조합이 될 수있는 이와 같은 사용법 :
[BsonSerializer(typeof(DictionarySerializer<
Dictionary<FeatureToggleTypeEnum, LicenseFeatureStateEnum>,
EnumStringSerializer<FeatureToggleTypeEnum>,
EnumStringSerializer<LicenseFeatureStateEnum>>))]
public Dictionary<FeatureToggleTypeEnum, LicenseFeatureStateEnum> FeatureSettings { get; set; }
참고 URL : https://stackoverflow.com/questions/6996399/storing-enums-as-strings-in-mongodb
'ProgramingTip' 카테고리의 다른 글
Maven을 사용하여 JAR의 "META-INF / services"폴더에 구성 파일을 포함하는 방법 (0) | 2020.11.17 |
---|---|
몽구스 연결 오류가 (0) | 2020.11.16 |
CAST DECIMAL을 INT로 (0) | 2020.11.16 |
twitter-bootstrap에서 텍스트 영역의 열을 어떻게 사용합니까? (0) | 2020.11.16 |
오류 메시지 : PDB 파일을 찾거나 열 수 없습니다. (0) | 2020.11.16 |