MyDbContext
をデータベースサービスレイヤーMyService
に挿入する方法を教えてください。
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(Configuration["ConnectionStrings:DefaultConnection"]));
services.AddMvc();
}
MyDbContext.cs
public partial class MyDbContext : DbContext
{
public virtual DbSet<User> User { get; set; }
public MyDbContext(DbContextOptions<MyDbContext> options)
:base(options)
{
}
}
appsettings.json
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
},
"ConnectionStrings": {
"DefaultConnection": "Server=MyServer;Database=MyDatabase;user id=MyUser;password=MyPassword;"
}
}
MyService.cs
public class MyService
{
public User GetUser(string username)
{
// Should i remove this call and get the reference from the injection somehow?
MyDbContext db_context = new MyDbContext(optionsBuilder.Options);
using (db_context)
{
var users = from u in db_context.User where u.WindowsLogin == username select u;
if (users.Count() == 1)
{
return users.First();
}
return null;
}
}
}
私のGetUser
メソッドでは、ここで注入されたMyDbContext
を使用することになっていることは知っていますが、それを取得する方法はよくわかりません。パズルのどのピースが欠けていますか?
Dbcontextを自分で含める必要はありません。ASP.NETコア依存性注入サービスがこれを行います。
スタートアップクラスでサービスとデータベースコンテキストを宣言し、必要なdbcontextをサービスのコンストラクタに配置するだけです。
Startup.cs(必要なサービスライフタイムを選択する必要があります。ここでは、リクエストごとにスコープサービスです):
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(Configuration["ConnectionStrings:DefaultConnection"]));
services.AddMvc();
services.AddScoped<IMyService, MyService>();
}
サービスクラス:
public class MyService : IMyService
{
private readonly MyDbContext _context;
public MyService(MyDbContext ctx){
_context = ctx;
}
public User GetUser(string username)
{
var users = from u in _context.User where u.WindowsLogin == username select u;
if (users.Count() == 1)
{
return users.First();
}
return null;
}
}
public interface IMyService
{
User GetUser(string username);
}
コントローラーでは、同じ方法で使用する必要があるサービス(またはデータベースコンテキスト)を宣言する必要があります。
public class TestController : Controller
{
private readonly IMyService _myService;
public TestController(IMyService serv)
{
_myService = serv;
}
public IActionResult Test()
{
return _myService.MyMethod(); // No need to instanciate your service here
}
}
コントローラーに関する注意:データベースコンテキストやサービスで行うように、スタートアップクラスに追加する必要はありません。コンストラクタを実装するだけです。
.NET Core依存性注入に関する詳細情報が必要な場合、公式ドキュメントは明確で非常に完全です: https://docs.Microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection
NB:startup.csでは、AddScoped行はオプションです。サービスに必要なライフタイムを選択できます。選択できるさまざまなライフタイムがあります。
一時的
一時的なライフタイムサービスは、要求されるたびに作成されます。このライフタイムは、軽量でステートレスなサービスに最適です。
スコープ
スコープ付きライフタイムサービスは、リクエストごとに1回作成されます。
シングルトン
シングルトンライフタイムサービスは、最初に要求されたときに(またはインスタンスを指定してConfigureServicesを実行したときに)作成され、その後のすべての要求は同じインスタンスを使用します。
上記から: https://docs.Microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection
注:ここでの質問ではありませんが、GetUserデータクエリは少し奇妙に見えます。 count()== 1の目標がユーザーのユニシティを確認することである場合、データベースにユニシティ制約を追加するのが良い方法です。 count()== 1の目標が、オブジェクトのnull参照例外を回避するためにデータがあることを確認することである場合、.FirstOrDefault()を使用できます。このメソッドを単純化できます:
public User GetUser(string username) => (from u in _context.User where u.WindowsLogin == username select u).FirstOrDefault();