Overview
このガイドでは、 .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] 属性をプロパティに適用します。
次のコード例では、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 をスローします。
注意
ネストされたドキュメント ID
このセクションで説明する _idフィールドのマッピング ロジックは、ルートドキュメントにのみ適用され、ネストされたドキュメントには適用されません。
ID ジェネレータを指定
MongoDB コレクション内のすべてのドキュメントには一意の ID が必要です。オブジェクトをコレクションに直列化する際、その ID プロパティがそのデータ型のデフォルト値(通常は null)を持つ場合、.NET/C# ドライバーはデフォルト値を直列化しません。代わりに、ドライバーは一意の ID 値を生成し、それをプロパティに割り当てようとします。
プロパティの ID 生成を有効にするには、ドライバーがプロパティに使用する ID ジェネレーターを指定する必要があります。プロパティに [BsonId] 属性を適用し、IdGenerator 引数を渡してジェネレーターの種類を指定できます。次の表は、.NET/C# ドライバーで利用可能な ID ジェネレーターについて示しています。
ID フィールドのデータ型 | 使用方法 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| COMB アルゴリズムを使用して一意の COMB アルゴリズムを使用せずに一意の | ||||||||||
| ドライバーは、次のコード例のように、 | ||||||||||
|
ID プロパティが | ||||||||||
| 次のコード例に示すように、ID プロパティに |
また、次の例に示すように、クラスマップを登録する際に 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ではない |
|
すべてがゼロではない |
|
次のコード例では、House クラスの Id プロパティにデフォルト値(null)が含まれている場合、ドライバーは例外をスローします。
public class House { [] public Guid Id { get; set; } }
空のフィールドを省略
デフォルトでは、ドライバーは未定義のプロパティを 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であるため、プロパティがこの値を持つ場合、ドライバーはプロパティを無視します。
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フレームワークの一部です。そのメンバーの詳細については、 Microsoft のドキュメントの DateTimeKind 列挙を参照してください。
辞書の直列化をカスタマイズ
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 ドキュメントを参照してください。