Entity Frameworkのコアのクエリ
同じクエリEF 6.xのとEntity Frameworkのコア・クエリが、より最適化されたSQLクエリ、およびC#/ VB.NET LINQ機能は、エンティティにクエリに含めることができます。
Entity Frameworkのコアを使用すると、関連するエンティティをロードするためのモデルでナビゲーションプロパティを使用することができます。3つの一般的なO / RMモードは、関連するデータをロードするために使用することができるがあります。
- イーガーローディング(前負荷):最初のクエリの一部として、データベースから関連するデータをロード示します。
- 明示的ローディング(明示的な負荷):後明示的データベースから関連するデータをロードすると述べました。
- レイジーローディング(装填遅延):透過データベースから関連データをロード属性ナビゲーションにアクセスする場合を示しています。
アクセスLINQツーエンティティ Entity Frameworkのクエリベースの詳細については、章を参照してください。
ここでは、導入されたクエリEntity Frameworkのコアの新機能を学習します。
クエリC#/ VB.NETの機能
LINQツーエンティティの新機能を備えたEFコア、我々はクエリでC#やVB.NETの機能を含めることができます。このEF 6はできません。
private static void Main(string[] args)
{
var context = new SchoolContext();
var studentsWithSameName = context.Students
.Where(s => s.FirstName == GetName())
.ToList();
}
public static string GetName() {
return "Bill";
}
上記L2Eクエリでは、我々は、関連項目GetName()C#関数でWhere句が含まれています。これは、データベースで次のクエリを実行します:
exec sp_executesql N'SELECT [s].[StudentId], [s].[DoB], [s].[FirstName],
[s].[GradeId], [s].[LastName], [s].[MiddleName]
FROM [Students] AS [s]
WHERE [s].[FirstName] = @__GetName_0',N'@__GetName_0 nvarchar(4000)',
@__GetName_0=N'Bill'
Go
イーガーロードプリロード
Entity Frameworkのコアを使用すると、()拡張メソッドと投影クエリがすぐに同じEF 6関連するエンティティをロードするために含めサポートしています。また、関連するエンティティの複数のレベルをロードするThenInclude()拡張メソッドを提供します。(EF 6はThenInclude()メソッドをサポートしません。)
含める:
EF 6とは異なり、我々は()メソッドは、ラムダ式のパラメータとして含める指定されることができ、ナビゲーションは以下に示すように、指定する属性。
var context = new SchoolContext();
var studentWithGrade = context.Students
.Where(s => s.FirstName == "Bill")
.Include(s => s.Grade)
.FirstOrDefault();
.INCLUDE(S => s.Grade)通過ラムダ式S => s.Grade、上記の例では、単一のSQLクエリで一緒にデータベース・エンティティ学生からデータがロードされた参照属性を指定するためです。上記のクエリは、データベースに次のSQLクエリを実行します。
SELECT TOP(1) [s].[StudentId], [s].[DoB], [s].[FirstName], [s].[GradeId],[s].[LastName],
[s].[MiddleName], [s.Grade].[GradeId], [s.Grade].[GradeName], [s.Grade].[Section]
FROM [Students] AS [s]
LEFT JOIN [Grades] AS [s.Grade] ON [s].[GradeId] = [s.Grade].[GradeId]
WHERE [s].[FirstName] = N'Bill'
私たちは、属性文字列は、同じEF 6を含めると名前でも()メソッドすることができます。
var context = new SchoolContext();
var studentWithGrade = context.Students
.Where(s => s.FirstName == "Bill")
.Include("Grade")
.FirstOrDefault();
名前のスペルが間違っているか、プロパティが存在しない場合は、実行時例外がスローされますので、我々は、上記の例を使用することはお勧めしません。それはコンパイル時にエラーを検出することができますので、必ず、ラムダ式の()メソッドを含める使用しています。
次のように含める()拡張メソッドもFromSql()メソッドの後に使用することができます。
var context = new SchoolContext();
var studentWithGrade = context.Students
.FromSql("Select * from Students where FirstName ='Bill'")
.Include(s => s.Grade)
.FirstOrDefault();
注:DbSet.Find()メソッドの後に含める()拡張メソッドを使用することはできません。たとえば。あなたはcontext.Students.Find(1).INCLUDE()EFコア2.0の中で使用することはできません。将来のリリースでは、これは可能かもしれません。
含める()メソッドを複数使用することは、同じ実体複数のナビゲーション属性をロードします。たとえば、次のコードのロードとStudentCoursesグレードスチューデント関連するエンティティ。
var context = new SchoolContext();
var studentWithGrade = context.Students.Where(s => s.FirstName == "Bill")
.Include(s => s.Grade)
.Include(s => s.StudentCourses)
.FirstOrDefault();
上記のクエリは、単一のデータベース・ラウンドトリップで2つのSQLクエリを実行します。
SELECT TOP(1) [s].[StudentId], [s].[DoB], [s].[FirstName], [s].[GradeId], [s].[LastName],
[s].[MiddleName], [s.Grade].[GradeId], [s.Grade].[GradeName], [s.Grade].[Section]
FROM [Students] AS [s]
LEFT JOIN [Grades] AS [s.Grade] ON [s].[GradeId] = [s.Grade].[GradeId]
WHERE [s].[FirstName] = N'Bill'
ORDER BY [s].[StudentId]
Go
SELECT [s.StudentCourses].[StudentId], [s.StudentCourses].[CourseId]
FROM [StudentCourses] AS [s.StudentCourses]
INNER JOIN (
SELECT DISTINCT [t].*
FROM (
SELECT TOP(1) [s0].[StudentId]
FROM [Students] AS [s0]
LEFT JOIN [Grades] AS [s.Grade0] ON [s0].[GradeId] = [s.Grade0].[GradeId]
WHERE [s0].[FirstName] = N'Bill'
ORDER BY [s0].[StudentId]
) AS [t]
) AS [t0] ON [s.StudentCourses].[StudentId] = [t0].[StudentId]
ORDER BY [t0].[StudentId]
Go
ThenInclude
EFコアは、エンティティに関連する複数のレベルをロードする新しいThenInclude()拡張メソッドを導入します。次の例を考えてみます。
var context = new SchoolContext();
var student = context.Students.Where(s => s.FirstName == "Bill")
.Include(s => s.Grade)
.ThenInclude(g => g.Teachers)
.FirstOrDefault();
上記の例では、.INCLUDEは(S => s.Grade)ナビゲーションプロパティグレード学生エンティティをロードしました。.ThenInclude(G => g.Teachers)グレード教師エンティティ属性のセットをロードしました。ThenInclude方法は含めるメソッドの後に呼び出さなければなりません。上記のコードは、データベースに次のSQLクエリを実行します。
SELECT TOP(1) [s].[StudentId], [s].[DoB], [s].[FirstName], [s].[GradeId], [s].[LastName],
[s].[MiddleName], [s.Grade].[GradeId], [s.Grade].[GradeName], [s.Grade].[Section]
FROM [Students] AS [s]
LEFT JOIN [Grades] AS [s.Grade] ON [s].[GradeId] = [s.Grade].[GradeId]
WHERE [s].[FirstName] = N'Bill'
ORDER BY [s.Grade].[GradeId]
Go
SELECT [s.Grade.Teachers].[TeacherId], [s.Grade.Teachers].[GradeId], [s.Grade.Teachers].[Name]
FROM [Teachers] AS [s.Grade.Teachers]
INNER JOIN (
SELECT DISTINCT [t].*
FROM (
SELECT TOP(1) [s.Grade0].[GradeId]
FROM [Students] AS [s0]
LEFT JOIN [Grades] AS [s.Grade0] ON [s0].[GradeId] = [s.Grade0].[GradeId]
WHERE [s0].[FirstName] = N'Bill'
ORDER BY [s.Grade0].[GradeId]
) AS [t]
) AS [t0] ON [s.Grade.Teachers].[GradeId] = [t0].[GradeId]
ORDER BY [t0].[GradeId]
go
投影クエリ(クエリ投影)
我々はまた、クエリの代わりに含めることができます()またはThenInclude()メソッドは、プロジェクターを使用して、複数の関連するエンティティをロードします。次の例では、「学生」、投影クエリ「年」と「先生」エンティティをロードするために使用示しています。
var context = new SchoolContext();
var stud = context.Students.Where(s => s.FirstName == "Bill")
.Select(s => new
{
Student = s,
Grade = s.Grade,
GradeTeachers = s.Grade.Teachers
})
.FirstOrDefault();
上記の例では、結果に使用.Select拡張方法は、学生、グレードおよび教師エンティティを含みます。これは、同じSQLクエリのThenInclude上記()メソッドを実行します。
遅延ロード(遅延ロード)と明示的にロードされる(明示的なロード)についてEFコア3.1は、元の2.0バージョンのサポートは、期限が切れている、あなたは、公式ドキュメントを参照することができます:
参考:https://docs.microsoft.com/en-us/ef/core/querying/related-data