web-dev-qa-db-ja.com

Entity Frameworkコアを使用したスト​​アドプロシージャの生成とアクセス

Asp.NetコアWeb API、エンティティフレームワークコア、Visual Studio 2017を使用したデータベースファーストアプローチを実装しています。既存のデータベースに基づいてコンテキストファイルとクラスファイルを生成することができました。コンテキストを使用してストアドプロシージャにアクセスする必要があります。エンティティフレームワークの以前のバージョンでは、ウィザードでストアドプロシージャオブジェクトを選択し、それらのオブジェクトを含むedmxを生成することで簡単でした。その後、エンティティフレームワークによって公開される複合型オブジェクトを介してストアドプロシージャにアクセスできます。エンティティフレームワークコアで同様のことを行うにはどうすればよいですか。例が役立ちますか?

12
Tom

EF Coreには、edmxファイルを使用したデータベースファーストのアプローチはありません。代わりにScaffold-DbContextを使用する必要があります

NugetパッケージMicrosoft.EntityFrameworkCore.ToolsおよびMicrosoft.EntityFrameworkCore.SqlServer.Designをインストールします

Scaffold-DbContext "Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models

ただし、ストアドプロシージャは取得されません。それはまだ作業中です、問題を追跡 #245

しかし、ストアドプロシージャを実行するには、RAW SQLクエリを実行する FromSql メソッドを使用します

例えば.

var products= context.Products
    .FromSql("EXECUTE dbo.GetProducts")
    .ToList();

パラメータで使用するには

var productCategory= "Electronics";

var product = context.Products
    .FromSql("EXECUTE dbo.GetProductByCategory {0}", productCategory)
    .ToList();

または

var productCategory= new SqlParameter("productCategory", "Electronics");

var product = context.Product
    .FromSql("EXECUTE dbo.GetProductByName  @productCategory", productCategory)
    .ToList();

RAW SQLクエリまたはストアドプロシージャの実行には特定の制限があります。INSERT/ UPDATE/DELETEには使用できません。 INSERT、UPDATE、DELETEクエリを実行する場合は、ExecuteSqlCommandを使用します

var categoryName = "Electronics";
dataContext.Database
           .ExecuteSqlCommand("dbo.InsertCategory @p0", categoryName);
15
Rohith

結果セットがすでに定義されているオブジェクトと同じであると予想される場合、ストアドプロシージャの実行時に上記の例は正常に機能します。しかし、サポートされていない結果セットが必要な場合はどうでしょうか? EF Core 2の開発者によると、これは今後登場する機能ですが、今日では既に簡単なソリューションがあります。

出力に使用するモデルを作成します。このモデルは、データベース内のテーブルではなく、出力を表します。

namespace Example.EF.Model
{
    public class Sample
    {
        public int SampleID { get; set; }
        public string SampleName { get; set; }
    }
}

次に、モデルに新しいDBSetをコンテキストに追加します。

public virtual DbSet<Sample> Sample { get; set; }

次に、上記のようにして、出力にモデルを使用します。

var products = _samplecontext.Sample
      .FromSql($"EXEC ReturnAllSamples {id}, {startdate}, {enddate}").ToList();

これが誰にとっても役立つことを願っています。

9
Sami

EF Coreでストアドプロシージャを実行してデータを取得するために使用する回避策は、FromSqlメソッドを使用することです。この方法でストアドプロシージャを実行できます。

List<Employee> employees = dbcontext.Employee
                    .FromSql("GetAllEmployees").ToList();

ただし、作成、更新、および削除には、次のようなExecuteSqlCommandを使用します。

var employee = "Harold Javier";
dbcontext.Employee
           .ExecuteSqlCommand("InsertEmployee @emp", employee);
2
Harold Javier

Rohith/Harold Javier/Samiのソリューションが作品を提供しました。別のEF6プロジェクトを作成して結果セット用のC#クラスを生成し、そのファイルをEFCoreプロジェクトにコピーできることを付け加えます。ストアドプロシージャを変更する場合、ここで説明する方法を使用して結果ファイルを更新できます。 ストアドプロシージャとEDMXの更新

対応するTypeScriptインターフェイスが必要な場合は、このVS2017拡張TypeScript定義ジェネレーターをインストールできます。 https://marketplace.visualstudio.com/items?itemName=MadsKristensen.TypeScriptDefinitionGenerator

まだいくつかのコピーがありますが、クラスを手動で作成するよりも面倒ではありません。

編集:dbconextを生成するためのVS2017拡張機能があります https://marketplace.visualstudio.com/items?itemName=ErikEJ.EFCorePowerTools 。ストアドプロシージャは実行しませんが、コマンドラインScaffold-DbContextの代わりにVSプロジェクトから右クリックメニュー項目を提供します。

1
Seanli

私の元の投稿- https://stackoverflow.com/a/57224037/1979465

ストアドプロシージャを呼び出して、結果をEF Coreのモデルのリストに取得するには、3つの手順に従う必要があります。

ステップ1。エンティティクラスと同じように新しいクラスを追加する必要があります。 SPのすべての列にプロパティが必要です。たとえば、SPがIdNameという2つの列を返している場合、新しいクラスは次のようになります。

public class MySPModel
{
    public int Id {get; set;}
    public string Name {get; set;}
}

ステップ2。

次に、1つのDbQueryプロパティをSPのDBContextクラスに追加する必要があります。

public partial class Sonar_Health_AppointmentsContext : DbContext
{
        public virtual DbSet<Booking> Booking { get; set; } // your existing DbSets
        ...

        public virtual DbQuery<MySPModel> MySP { get; set; } // your new DbQuery
        ...
}

ステップ3。

これで、DBContextからSPから呼び出して結果を取得できるようになります。

var result = await _context.Query<MySPModel>().AsNoTracking().FromSql(string.Format("EXEC {0} {1}", functionName, parameter)).ToListAsync();

汎用のUnitOfWorkとリポジトリを使用しています。だからSPを実行する私の関数は

/// <summary>
/// Execute function. Be extra care when using this function as there is a risk for SQL injection
/// </summary>
public async Task<IEnumerable<T>> ExecuteFuntion<T>(string functionName, string parameter) where T : class
{
    return await _context.Query<T>().AsNoTracking().FromSql(string.Format("EXEC {0} {1}", functionName, parameter)).ToListAsync();
}

それが誰かに役立つことを願っています!!!

0