web-dev-qa-db-ja.com

Entity Framework Core 2.1でSqlQueryを実行する方法は?

Entity Framework 6では、次のコマンドを使用してデータベースで生のSQLクエリを実行できます。

IEnumerable<string> Contact.Database.SqlQuery<string>("SELECT a.title FROM a JOIN b ON b.Id = a.aId WHERE b.Status = 10");

新しいプロジェクトでは、Entity Framework Core 2.1を使用しようとしています。生のSQLクエリを実行する必要があります。グーグル検索中に、拡張子SqlQueryFromSqlに変更されたことがわかります。ただし、FromSqlDbSet<>にのみ存在し、DbContext.Databaseには存在しません。

DbSet<>の外でFromSqlを実行するにはどうすればよいですか?メソッドFromSqlはデータベースオブジェクトDbContext.Database.FromSql<>に存在しません。

12
Junior

拡張機能SqlQueryがFromSqlに変更されたことがわかります

ただし、新しいFromSqlメソッドは、SqlQueryよりもリストラティブです。そのメソッドの documentation は、次のようないくつかの制限があることを説明しています。

SQLクエリは、モデルの一部であるエンティティタイプを返すためにのみ使用できます。 生のSQLクエリからアドホックタイプを返すことを可能にする のバックログが強化されました。

SQLクエリは、エンティティまたはクエリタイプのすべてのプロパティのデータを返す必要があります。

[...]

そのため、使用しているSQLクエリは次のとおりです。

SELECT a.title FROM a JOIN b ON b.Id = a.aId WHERE b.Status = 10

ドキュメントにあるように、FromSqlentityまたはクエリタイプでのみ使用できます。 SQLクエリは、モデルで定義されたエンティティのすべてのデータを返しませんが、エンティティの1列のみを返します。ちなみに、2018年5月7日以降にリリース候補版に含まれるEF Core 2.1に新しい機能が導入されました。Microsoftは次のように述べています。

EF Core 2.1 RC1は「Go Live」リリースです。つまり、アプリケーションがRC1で正常に動作することをテストしたら、本番環境で使用し、Microsoftからサポートを受けることができますが、利用可能になったら最終的な安定リリースに更新する必要があります。

クエリタイプでのFromSqlの使用

クエリタイプ :とは

EF Coreモデルにクエリタイプを含めることができるようになりました。エンティティタイプとは異なり、クエリタイプにはキーが定義されておらず、挿入、削除、または更新できません(つまり、読み取り専用です)が、クエリから直接返すことができます。クエリタイプの使用シナリオには、主キーのないビューへのマッピング、主キーのないテーブルへのマッピング、モデルで定義されたクエリへのマッピング、FromSql()クエリの戻り値の型として機能するものがあります。

最初にクラスを定義するSQLテキストでクエリタイプ機能を使用する場合は、MySuperClassという名前を付けましょう。

public class MySuperClass
{
    public string Title { get; set; }
}

次に、DbContextクラスで、以下のようにDbQuery<MySuperClass>型のプロパティを定義しました。

public DbQuery<MySuperClass> MySuperQuery { get; set; }

最後に、以下のようにFromSqlを使用できます:

var result = context.MySuperQuery.FromSql("SELECT a.title FROM a JOIN b ON b.Id = a.aId WHERE b.Status = 10").ToList().First();
var title = result.Title;

DbQuery<T>を使用したくない

DbQuery<T>を使用したくない場合、およびプロパティを1つだけ含むクラスを定義したくない場合は、@vivek nunaのようなExecuteSqlCommandAsyncを使用できます。 彼の答え(彼の答えは部分的に正しい)でした。ただし、そのメソッドから返される値がクエリの影響を受ける行の数であることを知っておく必要があります。また、クエリをストアドプロシージャにするために、タイトルを出力パラメーターとして配置する必要があります。 ExecuteSqlCommandAsyncまたはExecuteSqlCommandを使用し、その後、メソッドを呼び出すときに渡した出力パラメーターを読み取ります。

ストアドプロシージャを作成せずにExecuteSqlCommandAsyncまたはExecuteSqlCommandを使用しない簡単な方法は、次のコードです。

using (var context = new MyDbContext())
{
    var conn = context.Database.GetDbConnection();
    await conn.OpenAsync();
    var command = conn.CreateCommand();
    const string query = "SELECT a.title FROM a JOIN b ON b.Id = a.aId WHERE b.Status = 10";
    command.CommandText = query;
    var reader = await command.ExecuteReaderAsync();
    while (await reader.ReadAsync())
    {
        var title = reader.GetString(0);
        // Do whatever you want with title 
    }
}  

このロジックを、SQLクエリを受信して​​必要なデータを返すヘルパーメソッドにすることができます。しかし、 Dapper.Net を使用することをお勧めします。上記のようにRAW SQLを簡単に処理し、smae接続をDbContextと共有するのに役立つ多くのヘルパーメソッドが含まれています。

17
CodeNotFound

次の方法で、Microsoft.EntityFrameworkCore.Relational AssemblyのExecuteSqlCommandAsyncクラスで定義されているRelationalDatabaseFacadeExtensionsメソッドを使用できます。

_databaseContext.Database.ExecuteSqlCommandAsync(<Your parameters>)
3
vivek nuna