POCO
項目一覧
Overview
このガイドでは、操作とクエリに "Plain Old CLR/Class Objects" (POCO) を .NET/C# ドライバーと共に使用する方法について学ぶことができます。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]
属性をプロパティに適用します。
次のコード例では、Clothing
クラスの Upc
プロパティに [BsonElement]
属性を適用します。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 コレクションで別の命名規則またはカスタム命名規則を選択できます。
Tip
カスタムフィールド名の規則を設定する
すべてのプロパティをカスタムフィールド名で直列化する場合は、[BsonElement()]
属性を使用する代わりに ConventionPack
を定義できます。たとえば、パスカルケースの命名規則を使用してクラスを定義する場合、次のコードを使用して直列化されたドキュメントでキャメルケースのフィールド名を使用できます。
var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() }; ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);
型表現を選択する
C# プロパティを特定の BSON 型に直列化するには、 [BsonRepresentation()]
属性を使用します。これは、C# プリミティブ型が指定された BSON 型に変換可能な場合にのみ機能します。次のコード例では、C# で char
として定義されている YearBuilt
プロパティが BSON Int32
型として直列化されています。
public class House { public Guid Id { get; set; } [ ] public char YearBuilt { get; set; } }
有効な型変換の詳細については、「C# 変換の仕様」を参照してください。
フィールドの順序を設定
ドライバーは、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
が指定されていないプロパティの場合、ドライバーは 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
をスローします。
空のフィールドを省略
デフォルトでは、ドライバーは未定義のプロパティを 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)]
属性がない場合、ドライバーは Id
フィールドに割り当てる非 COMB GUID を生成します。
次の例に示すように、クラスマップを登録する際に IIdGenerator
型を指定することもできます。
BsonClassMap.RegisterClassMap<House>(classMap => { classMap.AutoMap(); classMap.MapIdMember(h => h.Id).SetIdGenerator(CombGuidGenerator.Instance); });
Tip
複数のクラスに対して IIdGenerator を指定する
RegisterIdGenerator()
メソッドを使用して、特定のデータ型のすべての Id
プロパティに対して 1 つの IIdGenerator
を指定できます。次のコード例では、すべての Guid
ID に対して CombGuidGenerator
型を使用するようにドライバーに指示します。
BsonSerializer.RegisterIdGenerator( typeof(Guid), CombGuidGenerator.Instance );
.NET/C# ドライバーには、Id
プロパティを検証し、ID が無効な場合に例外をスローする IIdGenerator
型も含まれています。次の表に、これらの型を示します。
ID の検証 | IIdGenerator タイプ |
---|---|
NULLではない | NullIdChecker |
すべてがゼロではない | ZeroIdChecker<T> |
次のコード例では、House
クラスの Id
プロパティにデフォルト値(null
)が含まれている場合、ドライバーは例外をスローします。
public class House { [ ] public Guid Id { get; set; } }
DateTime 直列化をカスタマイズ
.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)]
属性は、プロパティの値の時間コンポーネントがローカル時間であることを示します。ドライバーがこのプロパティを直列化する際、時刻を UTC に変換します。これは MongoDB に保存される時刻の標準形式です。
public class PatientRecord { public Guid Id { get; set; } [ ] public DateTime AppointmentTime { get; set; } }
クラスマップを登録するときに、前述の DateTime
オプションの 1 つまたは両方を指定することもできます。
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)); });
Tip
DateTimeKind Values
DateTimeKind
列挙型は .NET フレームワークの一部です。 そのメンバーの詳細について は、 DateTimeMany 列挙型に関する Microsoft のドキュメントを参照してください。
辞書の直列化をカスタマイズ
DictionaryRepresentation
列挙型は、.NET/C# ドライバーが Dictionary
インスタンスを直列化できる形式を定義します。この列挙型には、次のノードが含まれます。
Document:(デフォルト)ドライバーは
Dictionary
をBsonDocument
に直列化します。辞書内の各エントリは、名前がエントリのキーと等しく、値がエントリの値と等しい値を持つBsonElement
です。この表現を使用できるのは、辞書内のすべてのキーが有効なBsonElement
名でもある文字列の場合のみです。ArrayOfArrays: ドライバーは辞書を
BsonArray
に直列化します。辞書内の各エントリは、エントリのキーとエントリの値を含む、ネストされた 2 要素のBsonArray
です。ArrayOfDocuments: ドライバーは辞書を
BsonArray
に直列化します。辞書内の各エントリは{ k : key, v : value }
という形式のBsonDocument
がネストされています。キーと値には要素名がタグ付けされているので、ArrayOfArrays
よりも直感的にこの形式でクエリを実行できます。
次のコード例では、RoomSizes
プロパティは、家一軒の各部屋とその大きさを含む辞書となっています。[BsonDictionaryOptions()]
属性は、.NET/C# ドライバーに対して、このプロパティを BsonArray
オブジェクトに直列化し、辞書の各エントリを { k : "<room>", v : <size> }
形式の BsonDocument
に直列化するように指示します。
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()]
は、Price
フィールドを BSONDouble
型として直列化することを指定します。[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 ドキュメント を参照してください。
POCO を使用した追加の読み取りおよび書き込み操作の例については、 使用例または「CRUD の基礎」ページを参照してください。
ドライバーが BSON ドキュメントを POCO にマッピングする方法の詳細については、「クラスマッピング」を参照してください。
API ドキュメント
このガイドで説明したメソッドや型の詳細については、次の API ドキュメントを参照してください。