Entity Framework Coreでストアドプロシージャを使用する
ここでは、Entity Framework Coreでデータベースストアドプロシージャを実行する方法を学習します。
EF Coreには、ストアドプロシージャを実行するための次のメソッドが用意されています。
- DbSet <TEntity> .FromSql()
- DbContext.Database.ExecuteSqlCommand()
FromSqlまたはExecuteSqlCommandメソッドを使用してEF Core2でデータベースストアドプロシージャを実行する場合、いくつかの制限があります
。結果はエンティティタイプでなければなりません。つまり、ストアドプロシージャは、エンティティの対応するテーブルのすべての列を返す必要があります。
結果に関連データを含めることはできません。これは、ストアドプロシージャが結果を表すためにJOINを実行できないことを意味します。
挿入、更新、および削除のプロセスはこのエンティティにマップできないため、SaveChangesメソッドはCUD操作のストアドプロシージャを呼び出すことができません。
EF Coreでストアドプロシージャを実行する前に、MS SQL Serverでストアドプロシージャを作成してみましょう。
database-firstメソッドに従う場合は、ローカルSQL Serverデータベースで次のスクリプトを実行します。
USE [SchoolDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[GetStudents]
@FirstName varchar(50)
AS
BEGIN
SET NOCOUNT ON;
select * from Students where FirstName like @FirstName +'%'
END
GO
コードファーストの方法に従う場合は、次の手順に従ってください。
- NPM(NuGet Package Manager)で次のコマンドを実行して、空のマイグレーションを追加します。
Add-migration sp-GetStudents
2. <DateTime> _sp-GetStudents.csの空の移行クラスのUpメソッドに次のコードを記述します。
public partial class spGetStudents : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
var sp = @"CREATE PROCEDURE [dbo].[GetStudents]
@FirstName varchar(50)
AS
BEGIN
SET NOCOUNT ON;
select * from Students where FirstName like @FirstName +'%'
END";
migrationBuilder.Sql(sp);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
- コンソールで次のコマンドを実行して、データベースに上記のストアドプロシージャを作成します。
Update-database
これにより、SQL ServerデータベースにGetStudentsストアドプロシージャが作成されます。
FromSqlを使用してストアドプロシージャを実行する
前の章で述べたように、DbSetのFromSqlメソッドを使用して、基になるデータベースに対して生のSQLクエリを実行できます。同様に、エンティティデータを返すストアドプロシージャの実行にも使用できますが、いくつかの制限があります。
データベースでは、次のINPUTパラメータ値を使用してGetStudentsストアドプロシージャを実行できます。
GetStudents "Bill"
-- or
exec GetStudents "Bill"
次に示すように、EF CoreでFromSqlメソッドを使用して、上記と同じ方法でSPを実行できます。
var context = new SchoolContext();
var students = context.Students.FromSql("GetStudents 'Bill'").ToList();
以下に示すように、C#文字列補間構文を使用してパラメーター値を渡すこともできます。
var name = "Bill";
var context = new SchoolContext();
var students = context.Students
.FromSql($"GetStudents {name}")
.ToList();
//or
//var students = context.Students.FromSql($"exec GetStudents {name}").ToList();
SqlParameterインスタンスを使用して、次のようにINまたはOUTパラメーターの値を指定します。
var context = new SchoolContext();
var param = new SqlParameter("@FirstName", "Bill");
//or
/*var param = new SqlParameter() {
ParameterName = "@FirstName",
SqlDbType = System.Data.SqlDbType.VarChar,
Direction = System.Data.ParameterDirection.Input,
Size = 50,
Value = "Bill"
};*/
var students = context.Students.FromSql("GetStudents @FirstName", param).ToList();
最初のパラメーターには@ p0を、2番目のパラメーターには@ p1のように指定することもできます。
var context = new SchoolContext();
var students = context.Students.FromSql("GetStudents @p0","Bill").ToList();
上記の例では、名前付きパラメーターがEF Coreでまだサポートされていないため、最初のパラメーターに@ p0が使用されています。
注:デフォルトでは、DbContextは結果のすべてのエンティティを追跡します。同じストアドプロシージャを同じパラメーターで複数回実行すると、毎回同じSQLステートメントが実行されますが、追跡される結果セットは1つだけです。たとえば、次の例では、GetStudentsストアドプロシージャを3回実行しますが、結果のコピーをキャッシュして追跡するだけです。
var context = new SchoolContext();
var list1 = context.Students.FromSql("GetStudents 'Bill'").ToList();
var list2 = context.Students.FromSql("GetStudents 'Bill'").ToList();
var list3 = context.Students.FromSql("GetStudents 'Bill'").ToList();
ExecuteSqlCommand()を使用してストアドプロシージャを実行する
ExecuteSqlCommand()メソッドは、文字列の形式でデータベースコマンドを実行するために使用されます。指定されたコマンドの影響を受ける行数については、整数を返します。
var context = new SchoolContext();
var rowsAffected = context.Database.ExecuteSqlCommand("Update Students set FirstName = 'Bill' where StudentId = 1;");
上記の例では、更新コマンドはExecuteSqlCommandメソッドで渡されます。指定された更新コマンドの影響を受けるのは1行だけなので、rowsAffectedの値は1になります。
同様に、ストアドプロシージャを実行して、コマンドを作成、更新、および削除できます。データベースのStudentテーブルにレコードを挿入する次のストアドプロシージャを考えてみます。
CREATE PROCEDURE CreateStudent
@FirstName Varchar(50),
@LastName Varchar(50)
AS
BEGIN
SET NOCOUNT ON;
Insert into Students(
[FirstName]
,[LastName]
)
Values (@FirstName, @LastName)
END
GO
これで、上記のストアドプロシージャを実行できます。
var context = new SchoolContext();
context.Database.ExecuteSqlCommand("CreateStudents @p0, @p1", parameters: new[] { "Bill", "Gates" });
同様に、UpdateおよびDeleteコマンドのストアドプロシージャを実行できます。