【问题标题】:Injecting DbContext into service layer将 DbContext 注入服务层
【发布时间】:2016-12-09 10:21:43
【问题描述】:

我应该如何将我的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,但我不太确定如何获取它。我错过了哪一块拼图?

【问题讨论】:

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


    【解决方案1】:

    您不必自己包含 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


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

    瞬态

    每次请求时都会创建瞬态生命周期服务。 此生命周期最适合轻量级、无状态的服务。

    作用域

    范围内的生命周期服务为每个请求创建一次。

    单例

    单例生命周期服务在首次创建时创建 请求(或者如果您指定实例,则在运行 ConfigureServices 时 那里),然后每个后续请求都将使用相同的实例。

    以上摘自:https://docs.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();
    

    【讨论】:

    • 请始终将直接引用注明出处以避免抄袭。还将引号格式化为“引号”,以明确您引用的是外部来源
    • 您不必自己在控制器中实例化您的服务。我更新我的答案来添加这个
    • 我的答案中添加了控制器内容。依赖注入是 .NET 核心架构的一个非常重要的特性,我强烈建议您阅读相关文档。
    • 您是否在 GetUser 方法中删除了 using() ?您可以在答案中更新您的代码并添加控制器的代码吗?
    • 所有排序,非常感谢阿德里安。删除 using(_context) 完成了这项工作。
    猜你喜欢
    • 1970-01-01
    • 2013-12-18
    • 1970-01-01
    • 2021-10-20
    • 1970-01-01
    • 2018-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多