Overview
Entity Framework コアを使用すると、データベースコマンドを明示的に実行せずにアプリケーション内のデータを操作できます。 データをクエリするには、 LINQ(言語統合クエリ) 構文を使用します。 LINQ では、C# 固有のキーワードと演算子を使用して、厳密に型指定されたクエリを作成できます。 アプリケーションを実行すると、F Core プロバイダーは LINQ クエリを自動的に変換し、MongoDB Query API を使用してデータベース上で実行します。
このガイドでは、FS コア プロバイダーを使用するように構成されたアプリケーションにおける一般的なクエリ操作の例を確認できます。
Tip
FS コア プロバイダーを使用するようにアプリケーションを構成する方法については、「 FS コアの構成 」を参照してください。
サンプル データ
このガイドの例では、sample_guidesデータベースの planetsコレクションを使用します。このコレクションのドキュメントは、次の Planetクラスをモデルとして使用します。
public class Planet { public ObjectId _id { get; set; } public string name { get; set; } = null!; public int orderFromSun { get; set; } public bool hasRings { get; set; } }
このコレクションは、Atlas が提供する サンプルデータセット からのものです。MongoDBクラスターを無料で作成して、このサンプルデータをロードする方法については、クイック スタートガイドを参照してください。
エンティティの検索
FirstOrDefault()メソッドを使用して 1 つのエンティティを検索するか、 Where()メソッドを使用して複数のエンティティを検索します。
単一エンティティの検索
FirstOrDefault()メソッドは、コレクション内で検索条件に一致する最初に見つけたエンティティを返し、一致するエンティティが見つからない場合はnullを返します。
次のコードでは、 Planets FirstOrDefault() nameを使用して、 DBSet (
var planet = db.Planets.FirstOrDefault(p => p.name == "Mercury"); Console.WriteLine(planet?.name);
複数エンティティの検索
Where()メソッドを使用して、コレクションから複数のエンティティを取得できます。 Where()は、検索条件に一致するすべてのエンティティを返します。
次のコードでは、 Where()メソッドを使用して、 hasRingsフィールドがtrueに設定されているすべての惑星を検索し、惑星名をコンソールに出力します。
var planets = db.Planets.Where(p => p.hasRings); foreach (var p in planets) { Console.WriteLine(p.name); }
シャドウ プロパティのクエリ
A シャドウプロパティは、 .NETエンティティクラスで定義されていないプロパティですが、 Entity Framework モデルに含まれ、データベースのフィールドにマップされます。シャドウ プロパティを使用すると、エンティティのプロパティとして公開せずに、ドキュメント内のデータをクエリまたは追跡できます。
LINQ クエリでシャドウプロパティを参照には、EF.Property<T>() メソッドを呼び出し、構成されたプロパティ名を引数として渡します。ジェネリック型引数は、 シャドウプロパティのデータ型と一致する必要があります。
例、PlanetクラスはmainAtmosphereフィールドのプロパティを定義していません。このフィールドをシャドウプロパティとして構成するには、次の例に示すように、PlanetDbContext の OnModelCreating() メソッドで Property<T>() メソッドを呼び出します。
public class PlanetDbContext : DbContext { public DbSet<Planet> Planets { get; init; } = null!; public static PlanetDbContext Create(IMongoDatabase database) => new(new DbContextOptionsBuilder<PlanetDbContext>() .UseMongoDB(database.Client, database.DatabaseNamespace.DatabaseName) .Options); public PlanetDbContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<Planet>().ToCollection("planets"); modelBuilder.Entity<Planet>().Property<string[]>("mainAtmosphere"); } }
modelBuilder.Entity<Planet>().Property<string[]>("mainAtmosphere") を呼び出すと、モデルに mainAtmosphere を含め、それをMongoDBの string[]フィールドにマッピングするようにフレームワークに指示します。
次のコードでは、EF.Property<string[]>() メソッドを使用して、空でない mainAtmosphere プロパティを持つすべての惑星を検索し、惑星名をコンソールに出力します。
var planets = db.Planets.Where( p => EF.Property<string[]>(p, "mainAtmosphere").Length > 0); foreach (var p in planets) { Console.WriteLine(p.name); }
ソート エンティティ
クエリからエンティティを返す順序を指定するには、 OrderBy()メソッドを使用します。 OrderBy()は、指定された並べ替え条件に基づいて要素を昇順で並べ替えます。
次のコードでは、 OrderBy()メソッドを使用してすべての惑星を検索し、 orderFromSunフィールドの値で昇順に並べ替えます。 次に、結果をコンソールに出力します。
var planetList = db.Planets.OrderBy(p => p.orderFromSun); foreach (var p in planetList) { Console.WriteLine(p.name); }
{"_id":"...","name":"Mercury","orderFromSun":1,"hasRings":false} {"_id":"...","name":"Venus","orderFromSun":2,"hasRings":false} {"_id":"...","name":"Earth","orderFromSun":3,"hasRings":false} {"_id":"...","name":"Mars","orderFromSun":4,"hasRings":false} {"_id":"...","name":"Jupiter","orderFromSun":5,"hasRings":true} {"_id":"...","name":"Saturn","orderFromSun":6,"hasRings":true} {"_id":"...","name":"Uranus","orderFromSun":7,"hasRings":true} {"_id":"...","name":"Neptune","orderFromSun":8,"hasRings":true}
Tip
降順でソート
OrderByDescending()メソッドを使用して、クエリの結果を降順で並べ替えることができます。
ThenBy()メソッドを使用して、クエリで 2 次並べ替えを実行できます。 ThenBy()メソッドは、指定された並べ替え条件に基づいて、 OrderBy()メソッドの結果を昇順で並べ替えます。 ThenBy()メソッドはOrderBy()メソッドに連結する必要があります。
Tip
降順での二次ソート
ThenByDescending()メソッドを使用して、降順で二次並べ替えを実行できます。
次のコードでは、 OrderBy()メソッドとThenBy()メソッドを使用してすべての惑星を検索し、 hasRings()フィールドで並べ替え、 nameフィールドで 2 次並べ替えます。
var planetList = db.Planets.OrderBy(o => o.hasRings).ThenBy(o => o.name); foreach (var p in planetList) { Console.WriteLine("Has rings: " + p.hasRings + ", Name: " + p.name); }
{"_id":"...","name":"Earth","orderFromSun":3,"hasRings":false} {"_id":"...","name":"Mars","orderFromSun":4,"hasRings":false} {"_id":"...","name":"Mercury","orderFromSun":1,"hasRings":false} {"_id":"...","name":"Venus","orderFromSun":2,"hasRings":false} {"_id":"...","name":"Jupiter","orderFromSun":5,"hasRings":true} {"_id":"...","name":"Neptune","orderFromSun":8,"hasRings":true} {"_id":"...","name":"Saturn","orderFromSun":6,"hasRings":true} {"_id":"...","name":"Uranus","orderFromSun":7,"hasRings":true}
Tip
ブール値を持つフィールドでソートすると、フィールド値がfalse のエンティティがtrue のフィールド値より前に表示されます。
結果数を制限する
クエリから返されるエンティティの最大数を指定するには、Take() メソッドを使用します。
次のコードでは、Take() メソッドを使用して、Planetsコレクションから最初の 3 惑星を返します。
var planetList = db.Planets.Take(3); foreach (var p in planetList) { Console.WriteLine(p.name); }
結果をスキップする
Skip() メソッドを使用して、クエリから結果を返す前にスキップするエンティティの数を指定します。
次のコードでは、OrderBy() メソッドと Skip() メソッドを使用して、最初の 5 惑星(orderFromSun の順序)をスキップし、残りの惑星を返します。
var planetList = db.Planets.OrderBy(p => p.orderFromSun).Skip(5); foreach (var p in planetList) { Console.WriteLine(p.name); }
スカラー集計
FS コア プロバイダーは、次のスカラー集計メソッドをサポートしています。
Count():コレクション内の要素の数または述語に一致するドキュメントの数を返しますLongCount():コレクション内の要素の数をlongとして返すか、述語に一致するドキュメントの数を返しますAny():コレクション内のいずれかの要素が述語に一致する場合はtrueを返しますMax():コレクション内の指定されたフィールドの最大値を返しますMin():コレクション内の指定されたフィールドの最小値を返しますSum():コレクション内の指定されたフィールドの値の合計を返しますAverage():コレクション内の指定されたフィールドの値の平均を返します
次のセクションでは、前述の各方法の例を示します。
数
次の例では、Count() メソッドを使用して、Planetsコレクション内の要素の数をカウントします。
var planetCount = db.Planets.Count(); Console.WriteLine("Planet Count: " + planetCount);
次の例では、Count() メソッドを使用して、hasRingsフィールドが true に設定されている Planetsコレクション内の要素の数をカウントします。
var planetCountWithRings = db.Planets.Count(p => p.hasRings); Console.WriteLine("Planet Count with Rings: " + planetCountWithRings);
LongCount
次の例では、LongCount() メソッドを使用して Planetsコレクション内の要素の数をカウントし、その結果を long として返します。
var planetCountLong = db.Planets.LongCount(); Console.WriteLine("Long Planet Count: " + planetCountLong);
次の例では、LongCount() メソッドを使用して、hasRingsフィールドが true に設定されている Planetsコレクション内の要素の数をカウントし、その結果を long として返します。
var planetCountLongWithRings = db.Planets.LongCount(p => p.hasRings); Console.WriteLine("Long Planet Count with Rings: " + planetCountLongWithRings);
Any
次の例では、Any() メソッドを使用して、Planetsコレクション内のいずれかの要素で hasRingsフィールドが true に設定されているかどうかを確認します。
var results = db.Planets.Any(p => p.hasRings); Console.WriteLine("Planet with Rings: " + results);
Max
次の例では、Max() メソッドを使用して、Planetsコレクション内の orderFromSunフィールドの最大値を検索します。
var furthestPlanet = db.Planets.Max(p => p.orderFromSun); Console.WriteLine("Furthest Planet: " + furthestPlanet);
Min
次の例では、Min() メソッドを使用して、Planetsコレクション内の orderFromSunフィールドの最小値を検索します。
var closestPlanet = db.Planets.Min(p => p.orderFromSun); Console.WriteLine("Closest Planet: " + closestPlanet);
合計
次の例では、Sum() メソッドを使用して、Planetsコレクション内の orderFromSunフィールドの合計を求めます。
var totalOrderFromSun = db.Planets.Sum(p => p.orderFromSun); Console.WriteLine("Total Order From Sun: " + totalOrderFromSun);
平均
次の例では、Average() メソッドを使用して、Planetsコレクション内の orderFromSunフィールドの平均値を検索します。
var averageOrderFromSun = db.Planets.Average(p => p.orderFromSun); Console.WriteLine("Average Order From Sun: " + averageOrderFromSun);
MongoDBに送信されたクエリを調べる
LINQ クエリを作成した後、生成されたクエリを調べて、プロバイダーがMongoDB Serverに期待される形状を送信していることを確認します。開発中にクエリを検査するには、DbContext LogTo() メソッドを使用して、 で F Core ロギング を有効にします。
次の例は、 DbContextオブジェクトの作成時にコンソールへのログ記録を有効にする方法を示しています。
var mongoClient = new MongoClient("<connection string URI>"); var dbContextOptions = new DbContextOptionsBuilder<MyDbContext>() .UseMongoDB(mongoClient, "<database name>") .LogTo(Console.WriteLine) .Options; var db = new MyDbContext(dbContextOptions);
機密データ ログの有効化
プロバイダーは、機密データのログ記録が有効になっている場合にのみ、完全なMQLクエリテキストをログに記録します。機密データのログ記録 を有効にしないと、クエリ ログで 値が省略される可能性があります。機密データのログ記録を有効にするには、次の例に示すように、 DbContextOptionsBuilderオブジェクトから有効にする DataLoging() メソッドを呼び出します。
var mongoClient = new MongoClient("<connection string URI>"); var dbContextOptions = new DbContextOptionsBuilder<MyDbContext>() .UseMongoDB(mongoClient, "<database name>") .LogTo(Console.WriteLine) .EnableSensitiveDataLogging() .Options; var db = new MyDbContext(dbContextOptions);
重要
本番環境では を避ける
機密データのログ記録 は、開発環境でのみ有効にします。
カスタム直列化規則
キャメルケースのフィールド名など、MongoClient でカスタムBSON直列化規則を登録すると、それらの規則によってMongoDBに保存されるフィールド名が変更され、エンティティ モデルのプロパティ名と異なるものになる可能性があります。 FS コア プロバイダーはエンティティプロパティ名を使用してMQL を生成するため、不一致によってクエリが間違ったフィールドをターゲットにし、それらのフィールドのインデックスをバイパスする可能性があります。保存されたフィールド名がエンティティプロパティ名と異なる場合は、次の例に示すように、HasElementName() を使用して、OnModelCreating() にプロパティを明示的にマッピングできます。
protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<Planet>() .Property(p => p.name) .HasElementName("name"); }
Tip
.NET/ C#ドライバー モニタリング API
MongoDBコマンドの下位レベルの可視性が必要な場合は、 .NET/ C#ドライバー モニタリング API をMongoClient オブジェクトで使用できます。これらの API の詳細については、 .NET/ C#ドライバーのドキュメントの「 監視 」を参照してください。
詳細情報
MongoDBの集計の詳細については、 MongoDB Serverマニュアルの 集計操作ガイドを参照してください。
このガイドで説明されている FS Core メソッドの詳細については、次の.NET APIドキュメントへのリンクを参照してください。
このページで使用されている.NET/ C#ドライバー メソッドの詳細については、次のAPIドキュメント リンクを参照してください。
HasElementName() メソッドの詳細については、次の FA Core プロバイダーAPIドキュメント リンクを参照してください。