POCO
이 페이지의 내용
개요
이 가이드에서는 작업 및 쿼리에 .NET/C# 드라이버와 함께 "Plain Old CLR/Class Objects" 또는 POCO를 사용하는 방법에 대해 알아볼 수 있습니다. POCO는 프레임워크별 기본 클래스나 인터페이스의 기능을 상속하지 않는 간단한 클래스 객체입니다. 관용적인 드라이버 사용을 준수하고 최상의 성능을 얻으려면 C# 코드에서 POCO를 사용하는 것이 좋습니다.
.NET/C# 드라이버에서 POCO를 사용하는 방법에 대해 자세히 알아보고 싶거나 드라이버의 기본 필드 매핑 동작을 조정해야 하는 경우 이 가이드를 읽어야 합니다.
POCO 생성
인터페이스를 구현하지 않거나 프레임워크에서 클래스를 확장하지 않는 간단한 클래스를 정의하여 POCO를 만들 수 있습니다. POCO를 사용하여 읽기 또는 쓰기와 같은 작업을 실행하면 드라이버는 내부적으로 POCO를 BSON으로 직렬화하거나 변환합니다.
POCO 또는 BSON 탭을 선택하여 드라이버가 샘플 POCO를 BSON으로 직렬화하는 방법을 확인하세요.
public class Clothing { public ObjectId Id { get; set; } public string Name { get; set; } public bool InStock { get; set; } public double Price { get; set; } public List<string> ColorSelection { get; set; } }
{ "_id": ObjectId("..."), "Name": "Long Sleeve Shirt", "InStock": true, "Price": 17.99, "ColorSelection": [ "black", "navy", "red" ] }
중첩된 객체, 배열, 목록 및 모든 데이터 유형을 포함하여 필요에 맞는 객체 구조로 POCO를 정의할 수 있습니다.
사용자 지정 직렬화
기본 필드 매핑 동작이 요구 사항을 충족하지 않는 경우 직렬화 관련 특성을 사용하여 사용자 지정 동작을 지정할 수 있습니다. 이러한 특성은 드라이버가 POCO의 각 속성을 직렬화하는 방식을 변경합니다. 이 섹션에서는 일반적인 직렬화 관련 특성 중 일부를 설명합니다.
읽기 전용 속성 직렬화
속성이 읽기 전용인 경우 자동 매퍼는 직렬화를 위해 클래스 맵에 해당 속성을 포함하지 않습니다. 자동 매퍼가 클래스 맵에 속성을 포함하도록 하려면 해당 속성에 [BsonElement]
특성을 적용합니다.
다음 코드 예시에서는 [BsonElement]
특성을 Clothing
클래스의 Upc
속성에 적용합니다. Upc
는 get
메서드는 있지만 set
메서드가 없으므로 읽기 전용 속성입니다.
public class Clothing { public ObjectId Id { get; set; } public string Name { get; set; } public bool InStock { get; set; } public double Price { get; set; } public List<string> ColorSelection { get; set; } [ ] public int Upc { get; } }
다음 예시와 같이 클래스 맵을 등록할 때 읽기 전용 속성을 추가할 수도 있습니다.
BsonClassMap.RegisterClassMap<Clothing>(classMap => { classMap.AutoMap(); classMap.MapProperty(c => c.Upc); });
참고
.NET/C# 드라이버가 읽기 전용 속성을 직렬화할 때 속성과 해당 값은 데이터베이스에 저장되지만 다시 역직렬화되지는 않습니다.
필드 이름 설정
드라이버는 POCO 속성을 필드 이름과 대소문자가 동일한 BSON 필드로 직렬화합니다. 속성을 다른 이름으로 저장하려면 [BsonElement()]
특성을 사용합니다. 다음 코드는 House
클래스의 YearBuilt
속성을 직렬화된 BSON 문서의 year_built
필드에 매핑합니다.
public class House { public Guid Id { get; set; } [ ] public int YearBuilt { get; set; } }
C# 클래스를 정의할 때 파스칼 대소문자 명명 규칙을 사용하는 것이 일반적이지만 [BsonElement()]
특성을 사용하면 MongoDB 컬렉션에서 다른 또는 사용자 지정 명명 규칙을 선택할 수 있습니다.
팁
사용자 지정 필드 이름 규칙 설정
사용자 지정 필드 이름으로 모든 속성을 직렬화하려면 [BsonElement()]
특성을 사용하는 대신 ConventionPack
을 정의하면 됩니다. 예를 들어, 파스칼 대소문자 명명 규칙을 사용하여 클래스를 정의하는 경우 다음 코드를 사용하여 직렬화된 문서에서 카멜식 필드 이름을 사용할 수 있습니다.
var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() }; ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);
유형 표현 선택
C# 속성을 특정 BSON type으로 직렬화하려면 [BsonRepresentation()]
특성을 사용합니다. 이는 C# 기본 유형을 지정한 BSON type으로 변환할 수 있는 경우에만 작동합니다. 다음 코드 샘플에서 C#에서 char
로 정의된 YearBuilt
속성은 BSON Int32
유형으로 직렬화됩니다.
public class House { public Guid Id { get; set; } [ ] public char YearBuilt { get; set; } }
유효한 유형 변환에 대한 자세한 내용은 C# 변환 사양을 참조하세요.
중요
NaN과 Infinity 직렬화
부동 소수점 Infinity
또는 NaN
값을 정수 표현으로 직렬화하거나 역직렬화하려고 하면 드라이버에서 OverflowException
이 발생합니다.
필드 순서 설정
드라이버는 POCO에 지정된 순서대로 BSON 필드에 속성을 직렬화합니다. 기존 스키마와 일치하도록 사용자 지정 순서로 속성을 저장하려면 [BsonElement()]
특성에 매개변수가 명명된 Order
를 지정할 수 있습니다. 다음 코드 샘플에서 드라이버는 Style
속성 뒤에 YearBuilt
속성을 저장합니다.
public class House { public Guid Id { get; set; } [ ] public int YearBuilt { get; set; } [ ] public string Style { get; set; } }
속성에 명시적 Order
가 없는 경우 드라이버는 명시적 값이 있는 속성 다음에 해당 속성을 기본 순서로 직렬화합니다.
Id
속성 식별
기본적으로 드라이버는 Id
, id
또는 _id
라는 공용 속성을 BSON _id
필드에 매핑합니다. _id
필드에 매핑할 속성을 명시적으로 선택하려면 [BsonId()]
특성을 사용합니다. 다음 코드 샘플에서는 Identifier
속성을 _id
필드에 매핑합니다.
public class House { [ ] public string Identifier { get; set; } }
경고
여러 ID 필드
[BsonId()]
특성을 사용하여 둘 이상의 속성을 _id
필드로 식별하면 드라이버는 DuplicateBsonMemberMapAttributeException
을 발생시킵니다. 동일한 데이터베이스 필드를 두 번 이상 지정하는 경우(예시: POCO에 Id
및 _id
라는 속성이 포함된 경우) 드라이버는 BsonSerializationException
을 발생시킵니다.
참고
중첩된 문서 ID
이 섹션에서 설명하는 _id
필드 매핑 로직은 루트 문서 에만 적용되며 중첩된 문서에는 적용 되지 않습니다.
빈 필드 생략
기본적으로 드라이버는 정의되지 않은 속성을 null
값이 있는 필드로 직렬화합니다. 직렬화 중에 정의되지 않은 속성을 무시하려면 [BsonIgnore]
특성을 사용합니다. 다음 코드는 YearBuilt
속성이 정의되지 않은 경우 드라이버가 해당 속성을 직렬화하지 못하게 하는 방법을 보여줍니다.
public class House { public Guid Id { get; set; } [ ] public int YearBuilt { get; set; } public string Style { get; set; } }
기본값 사용자 지정
C#에서 속성은 값을 할당하기 전까지는 기본값이 있습니다. 기본값은 속성의 데이터 유형에 따라 다릅니다. 예를 들어, 참조 유형 속성의 기본값은 null
입니다.
속성에 대해 다른 기본값을 지정하려면 [BsonDefaultValue()]
특성을 속성에 적용하고 원하는 기본값을 인수로 전달합니다.
다음 코드 예시에서는 [BsonDefaultValue()]
특성을 YearBuilt
속성에 적용합니다. 이 속성에 값이 할당될 때까지 해당 값은 1900
입니다.
public class House { public Guid Id { get; set; } [ ] public int YearBuilt { get; set; } }
다음 예시와 같이 클래스 맵을 등록할 때 속성에 대해 다른 기본값을 지정할 수도 있습니다.
BsonClassMap.RegisterClassMap<House>(classMap => { classMap.AutoMap(); classMap.MapMember(h => h.YearBuilt).SetDefaultValue(1900); });
기본적으로 .NET/C# 드라이버는 기본값이 포함된 속성을 포함하여 모든 속성을 직렬화합니다. 기본값이 있는 속성을 무시하도록 드라이버에 지시하려면 [BsonIgnoreIfDefault]
특성을 사용합니다.
다음 코드 예시에서는 [BsonIgnoreIfDefault]
특성을 YearBuilt
속성에 적용합니다. 이 속성의 값이 데이터 유형의 기본값( int
속성의 경우 0
)인 경우 드라이버는 이를 직렬화하지 않습니다.
public class House { public Guid Id { get; set; } [ ] public int YearBuilt { get; set; } }
다음 예시와 같이 클래스 맵을 등록할 때 기본값이 포함된 속성을 무시하도록 드라이버에 지시할 수도 있습니다.
BsonClassMap.RegisterClassMap<House>(classMap => { classMap.AutoMap(); classMap.MapMember(h => h.YearBuilt).SetIgnoreIfDefault(true); });
속성에 다른 기본값을 지정하고 이 기본값이 포함된 경우 해당 속성을 무시하도록 드라이버에 지시할 수 있습니다. 이렇게 하려면 다음 코드 예시와 같이 [BsonDefaultValue()]
및 [BsonIgnoreIfDefault]
특성을 속성에 모두 적용합니다.
public class House { public Guid Id { get; set; } [ ] [ ] public int YearBuilt { get; set; } }
이전 코드 예시에서는 다음과 같은 직렬화 동작을 설정합니다.
YearBuilt
속성에 값이 할당되지 않은 경우 지정된 기본값은1900
입니다.1900
이 속성의 기본값이므로 드라이버는 이 값이 있는 경우 속성을 무시합니다.
ID 생성기 지정
MongoDB 컬렉션의 모든 문서에는 고유 ID가 있어야 합니다. 객체를 컬렉션에 직렬화할 때 Id
속성에 해당 데이터 유형의 기본값이 포함되어 있으면 .NET/C# 드라이버는 해당 객체를 직렬화하지 않습니다. 대신 드라이버는 속성에 대한 고유 ID 값을 생성합니다.
Id
속성이 Guid
, ObjectId
또는 string
유형인 경우 드라이버는 자체적으로 ID 값을 생성할 수 있습니다. Id
속성이 다른 데이터 유형인 경우 드라이버가 값을 생성하는 데 사용하는 IIdGenerator
유형을 지정해야 합니다. IIdGenerator
유형을 지정하려면 [BsonId(IdGenerator)]
특성을 속성에 적용하고 IIdGenerator
유형을 인수로 전달합니다.
.NET/C# 드라이버에는 다음과 같은 IIdGenerator
유형이 포함되어 있습니다.
Id 필드 데이터 유형 | IIdGenerator 유형 |
---|---|
Guid COMB 알고리즘에 의해 생성된 값 | CombGuidGenerator |
BsonObjectId | BsonObjectIdGenerator |
다음 코드 예시에서 House
클래스의 Id
속성에 기본값(null
)이 포함된 경우 드라이버는 직렬화 중에 COMB 알고리즘을 사용하여 고유한 값을 생성합니다.
public class House { [ ] public Guid Id { get; set; } }
참고
이전 코드 예시에서 Id
속성에 [BsonId(IdGenerator)]
특성이 없는 경우 드라이버는 Comb가 아닌 GUID를 생성하여 Id
필드에 할당합니다.
다음 예와 같이 클래스 맵을 등록하는 동안 IIdGenerator
유형을 지정할 수도 있습니다.
BsonClassMap.RegisterClassMap<House>(classMap => { classMap.AutoMap(); classMap.MapIdMember(h => h.Id).SetIdGenerator(CombGuidGenerator.Instance); });
팁
여러 클래스에 대한 IIdGenerator 지정
RegisterIdGenerator()
메서드를 사용하여 특정 데이터 유형의 모든 Id
속성에 대해 단일 IIdGenerator
를 지정할 수 있습니다. 다음 코드 예시는 드라이버가 모든 Guid
ID에 대해 CombGuidGenerator
유형을 사용하도록 지시합니다.
BsonSerializer.RegisterIdGenerator( typeof(Guid), CombGuidGenerator.Instance );
NET/C# 드라이버에는 Id
속성의 유효성을 검사하고 ID가 유효하지 않은 경우 예외를 발생시키는 IIdGenerator
유형도 포함되어 있습니다. 다음 표에는 이러한 유형이 나와 있습니다.
ID 유효성 검사 | IIdGenerator 유형 |
---|---|
null이 아님 | NullIdChecker |
0이 아님 | ZeroIdChecker<T> |
다음 코드 예시에서 House
클래스의 Id
속성에 기본값(null
)이 포함된 경우 드라이버에서 예외가 발생합니다.
public class House { [ ] public Guid Id { get; set; } }
날짜/시간 직렬화 사용자 지정
.NET/C# 드라이버가 DateTime
속성을 직렬화하는 방법을 사용자 지정하려면 [BsonDateTimeOptions()]
특성을 사용하고 원하는 설정을 인수로 지정합니다.
DateTime
속성이 날짜만 나타내는 경우 [BsonDateTimeOptions(DateOnly = true)]
특성을 적용할 수 있습니다. 그렇게 하면 드라이버는 값에 대해 시간대 변환을 수행하지 않습니다.
다음 코드 예시에서 PatientRecord
클래스는 DateOfBirth
속성에 DateTime
을 사용합니다. [BsonDateTimeOptions(DateOnly = true)]
특성은 속성에 날짜만 포함되어 있음을 나타냅니다.
public class PatientRecord { public Guid Id { get; set; } [ ] public DateTime DateOfBirth { get; set; } }
[BsonDateTimeOptions()]
특성을 사용하여 DateTime
속성의 DateTimeKind
를 지정할 수도 있습니다. 다음 코드 예시에서 PatientRecord
클래스에는 DateTime
유형의 AppointmentTime
속성이 있습니다. [BsonDateTimeOptions(Kind = DateTimeKind.Local)]
특성은 속성 값의 시간 구성 요소가 현지 시간임을 나타냅니다. 드라이버는 이 속성을 직렬화할 때 시간을 MongoDB에 저장된 표준 시간 형식인 UTC로 변환합니다.
public class PatientRecord { public Guid Id { get; set; } [ ] public DateTime AppointmentTime { get; set; } }
클래스 맵을 등록할 때 이전 DateTime
옵션 중 하나 또는 둘 다를 지정할 수도 있습니다.
BsonClassMap.RegisterClassMap<House>(classMap => { classMap.AutoMap(); classMap.MapMember(p => p.DateOfBirth) .SetSerializer(new DateTimeSerializer(dateOnly: true)); classMap.MapMember(p => p.AppointmentTime) .SetSerializer(new DateTimeSerializer(DateTimeKind.Local)); });
팁
DateTimeKind Values
DateTimeKind
열거형은 .NET 프레임워크의 일부입니다. 해당 멤버에 대한 자세한 내용은 DateTimeKind 열거형에 대한 Microsoft 문서를 참조하세요.
사전 직렬화 사용자 지정
DictionaryRepresentation
열거형은 .NET/C# 드라이버가 Dictionary
인스턴스를 직렬화할 수 있는 형식을 정의합니다. 이 열거형에는 다음 노드가 포함됩니다.
문서: (기본값) 드라이버는
Dictionary
를BsonDocument
로 직렬화합니다. 사전의 각 항목은 항목 키와 이름이 같고 값이 항목 값과 같은BsonElement
입니다. 사전의 모든 키가 유효한BsonElement
이름이기도 한 문자열인 경우에만 이 표현을 사용할 수 있습니다.ArrayOfArrays: 드라이버가 사전을
BsonArray
로 직렬화합니다. 사전의 각 항목은 항목 키와 항목 값을 포함하는 중첩된 두 요소로 구성된BsonArray
입니다.ArrayOfDocuments: 드라이버는 사전을
BsonArray
로 직렬화합니다. 사전의 각 항목은{ k : key, v : value }
형식의 중첩된BsonDocument
입니다. 키와 값에 요소 이름이 태그되어 있으므로 이 형식은ArrayOfArrays
보다 더 직관적으로 쿼리할 수 있습니다.
다음 코드 예시에서 RoomSizes
속성은 집의 각 방과 해당 크기를 포함하는 사전입니다. [BsonDictionaryOptions()]
특성은 이 속성을 BsonArray
객체로, 사전의 각 항목을 { k : "<room>", v : <size> }
형식의 BsonDocument
로 직렬화하도록 .NET/C# 드라이버에 지시합니다.
public class House { public Guid Id { get; set; } [ ] public Dictionary<string, float> RoomSizes { get; set; } }
다음 예시와 같이 클래스 맵을 등록할 때 사전의 직렬화 형식을 지정할 수도 있습니다.
BsonClassMap.RegisterClassMap<House>(classMap => { classMap.AutoMap(); classMAp.MapMember(h => h.RoomSizes) .SetSerializer(new DictionaryInterfaceImplementerSerializer<Dictionary<string, float>> (DictionaryRepresentation.ArrayOfDocuments)); });
예시
다음 예에서는 사용자 지정 필드 매핑 사양이 있는 Clothing
문서를 MongoDB에 삽입하는 방법을 보여줍니다.
다음 코드는 이러한 직렬화 관련 특성을 가진 Clothing
클래스를 정의합니다.
[BsonElement()]
카멜식 명명 규칙으로 사용자 지정 필드 이름을 지정합니다.[BsonRepresentation()]
BSONDouble
유형으로Price
필드의 직렬화를 지정합니다.[BsonDefaultValue()]
값이 할당되지 않은 경우Name
속성을"Generic item"
으로 설정합니다.[BsonDateTimeOptions(DateOnly = true)]
DateTime
속성이 관련된 시간 없이 날짜 값만 나타내도록 지정합니다.
public class Clothing { public ObjectId Id { get; set; } [ ] [ ] public string Name { get; set; } [ ] public bool InStock { get; set; } [ ] [ ] public decimal Price { get; set; } [ ] public List<string> ColorSelection { get; set; } [ ] [ ] public DateTime ListedDate { get; set; } [ ] public Dictionary<string, string> SizeGuide { get; set; } }
다음 코드는 Clothing
객체를 인스턴스화하고 문서를 컬렉션에 삽입합니다.
var doc = new Clothing { Name = "Denim Jacket", InStock = false, Price = 32.99m, ColorSelection = new List<string> { "dark wash", "light wash" }, ListedDate = DateTime.Parse("Jan 1, 2007"), SizeGuide = new Dictionary<string, string>() { {"Small", "Chest: 38\", Waist: 38\", Shoulders: 15\""}, {"Medium", "Chest: 40\", Waist: 40\", Shoulders: 15.5\""}, {"Large", "Chest: 42\", Waist: 40\", Shoulders: 16\""} } }; _myColl.InsertOne(doc);
삽입된 문서의 BSON 표현은 다음과 같습니다.
{ "_id": ObjectId("..."), "name": "Denim Jacket", "inStock": false, "price": 32.99, "colorSelection": [ "dark wash", "light wash" ], "listedDate" : ISODate("2007-01-01T00:00:00Z"), "sizeGuide" : { "Small" : "Chest: 38\", Waist: 38\", Shoulders: 15\"", "Medium" : "Chest: 40\", Waist: 40\", Shoulders: 15.5\"", "Large" : "Chest: 42\", Waist: 40\", Shoulders: 16\"" } }
추가 정보
직렬화 관련 특성의 전체 목록은 Serialization.Attributes API(직렬화 특성 API) 문서를 참조하세요.
POCO를 사용한 추가 읽기 및 쓰기 작업 예시는 사용 예시 또는 CRUD 기본 사항 페이지를 참조하세요.
드라이버가 BSON 문서를 POCO에 매핑하는 방법에 대해 자세히 알아보려면 클래스 매핑을 참조하세요.
API 문서
이 가이드에서 사용되는 메서드 또는 유형에 대해 자세히 알아보려면 다음 API 설명서를 참조하세요.