生 SQL クエリ (EF6)

Entity Framework では、エンティティ クラスで LINQ を使用してクエリを実行できます。 ただし、生 SQL を使用したクエリをデータベースに対して直接実行したい場合もあります。 これには、ストアド プロシージャの呼び出しが含まれます。これは、ストアド プロシージャへのマッピングが現在サポートされていない Code First モデルで役立ちます。 このトピックで紹介するテクニックは、Code First および EF Designer で作成されたモデルに等しく使用できます。

エンティティの SQL クエリを記述する

DbSet の SqlQuery メソッドを使用すると、エンティティ インスタンスを返す生 SQL クエリを記述できます。 返されるオブジェクトは、LINQ クエリによって返される場合と同様に、コンテキストによって追跡されます。 次に例を示します。

using (var context = new BloggingContext())
{
    var blogs = context.Blogs.SqlQuery("SELECT * FROM dbo.Blogs").ToList();
}

LINQ クエリの場合と同様に、結果が列挙されるまでクエリは実行されません。上記の例では、これは ToList の呼び出しで実行されます。

2 つの理由から、生 SQL クエリを記述するときには常に注意が必要です。 第 1 に、実際に要求された型のエンティティだけを返すようにクエリを記述する必要があります。 たとえば、継承などの機能を使用する場合、間違った CLR 型のエンティティを作成するクエリを記述しがちです。

第 2 に、生 SQL クエリの種類によっては、特に SQL インジェクション攻撃に関するセキュリティ リスクが発生する可能性があります。 このような攻撃から保護するには、クエリのパラメーターを正しい方法で使用する必要があります。

ストアド プロシージャからエンティティを読み込む

DbSet.SqlQuery を使用して、ストアド プロシージャの結果からエンティティを読み込むことができます。 たとえば、次のコードでは、データベースの dbo.GetBlogs プロシージャを呼び出します。

using (var context = new BloggingContext())
{
    var blogs = context.Blogs.SqlQuery("dbo.GetBlogs").ToList();
}

次の構文を使用して、ストアド プロシージャにパラメーターを渡すこともできます。

using (var context = new BloggingContext())
{
    var blogId = 1;

    var blogs = context.Blogs.SqlQuery("dbo.GetBlogById @p0", blogId).Single();
}

非エンティティ型の SQL クエリを記述する

プリミティブ型など、任意の型のインスタンスを返す SQL クエリは、Database クラスの SqlQuery メソッドを使用して作成できます。 次に例を示します。

using (var context = new BloggingContext())
{
    var blogNames = context.Database.SqlQuery<string>(
                       "SELECT Name FROM dbo.Blogs").ToList();
}

Database の SqlQuery から返される結果は、オブジェクトがエンティティ型のインスタンスであっても、コンテキストによって追跡されることはありません。

生のコマンドをデータベースに送信する

非クエリ コマンドは、Database の ExecuteSqlCommand メソッドを使用してデータベースに送信できます。 次に例を示します。

using (var context = new BloggingContext())
{
    context.Database.ExecuteSqlCommand(
        "UPDATE dbo.Blogs SET Name = 'Another Name' WHERE BlogId = 1");
}

ExecuteSqlCommand を使用してデータベースのデータに加えられた変更は、エンティティがデータベースから読み込まれるか、再読み込みされるまで、コンテキストに対して不透明であることに注意してください。

出力パラメーター

出力パラメーターが使用されている場合、結果が完全に読み取られるまで値は使用できません。 これは、DbDataReader の基になる動作に起因します。詳細については、DataReader を使用したデータの取得に関する記事を参照してください。