我应该如何将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
,但我不太确定如何获取它。我错过了哪一块拼图?
答案 0 :(得分:21)
您不必自己包含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行是一个选项。您可以选择所需的服务期限。 您可以选择不同的生命周期:
<强>瞬态强>
每次请求时都会创建瞬态生命周期服务。 这种生命周期最适合轻量级无状态服务。
<强>作用域强>
每个请求都会创建一次范围生命周期服务。
<强>的Singleton 强>
Singleton生命周期服务是在第一次创建时创建的 请求(或者在指定实例时运行ConfigureServices时) 那里)然后每个后续请求将使用相同的实例。
以上摘自:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection
注意:这不是问题,但您的GetUser数据查询对我来说有点奇怪。如果你的count()== 1目标是检查用户的单一性,那么好的方法是在数据库中添加unicity约束。如果count()== 1目标是检查你有数据以避免对象空引用异常,你可以使用.FirstOrDefault(),它会为你管理这个。您可以简化此方法:
public User GetUser(string username) => (from u in _context.User where u.WindowsLogin == username select u).FirstOrDefault();