c# - 将 DbContext 注入(inject)服务层

标签 c# entity-framework asp.net-core-mvc

我应该如何将我的 MyDbContext 注入(inject)到我的数据库服务层 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 方法中,我知道我应该在这里使用我注入(inject)的 MyDbContext 但我不太确定如何获取它。我错过了哪一 block 拼图?

最佳答案

您不必自己包含 dbcontext,ASP.NET Core 依赖注入(inject)服务会为您做这件事。

您只需在启动类中声明您的服务和数据库上下文,并将您需要的 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);
}

在您的 Controller 中,您必须以相同的方式声明您需要使用的服务(或数据库上下文):

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
      }
}

关于 Controller 的注意事项:您不必像处理数据库上下文或服务那样将它们添加到启动类中。只需实现它们的构造函数即可。

如果您需要有关 .NET Core 依赖注入(inject)的更多信息,官方文档清晰且非常完整:https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection


注意: 在 startup.cs 中,AddScoped 行是一个选项。您可以选择您想要的服务生命周期。 您可以选择不同的生命周期:

Transient

Transient lifetime services are created each time they are requested. This lifetime works best for lightweight, stateless services.

Scoped

Scoped lifetime services are created once per request.

Singleton

Singleton lifetime services are created the first time they are requested (or when ConfigureServices is run if you specify an instance there) and then every subsequent request will use the same instance.

以上摘自:https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection


注意:这不是这里的问题,但我觉得您的 GetUser 数据查询有点奇怪。如果您的 count()==1 目标是检查用户的唯一性,那么好的方法是在您的数据库中添加一个唯一性约束。如果 count()==1 目标是检查您是否有数据以避免对象空引用异常,您可以使用 .FirstOrDefault(),它将为您管理。您可以简化此方法:

public User GetUser(string username) => (from u in _context.User where u.WindowsLogin == username select u).FirstOrDefault();

关于c# - 将 DbContext 注入(inject)服务层,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41058142/

相关文章:

c# - 如何为依赖于 DbEntityEntry 的对象创建单元测试

c# - 尝试下载单词时出现“无法访问关闭的流”之类的错误

iis-express - 可以将iis Express配置(Windows身份验证)添加到asp.net mvc6项目吗?

c# - LINQ Max() 函数执行速度超慢

c# - 如何使用包含多个工作表的 OOXML SDK 创建新的电子表格文件?

c# - WPF DataGrid 父子数据

c# - 如何加快此 LINQ 查询的速度?

c# - 无法将类型 'x' 转换为类型 'y'。 LINQ to Entities 仅支持转换 EDM 原语或枚举类型

entity-framework - Entity Framework 6 和 ObjectCache : saving issues

asp.net-core-mvc - 区域未传递给 ASP.net Core 中的 Url.Action()