通过SignalR Core访问DB上下文

时间:2018-06-16 06:45:30

标签: c# signalr dbcontext signalr-hub asp.net-core-signalr

我正在使用AspNetCore.SignalR,我需要有关如何通过我的Hub访问我的SQL Server数据库的建议。关于此,没有太多资源。我知道如何添加单例,但我不知道如何在以后访问它。如何在Hub的任务中访问使用Startup.cs中的Configuration.GetConnectionString定义的数据库上下文?

感谢。

以下是相关代码:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
        });


    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    DbContextOptionsBuilder<PlayerContext> PlayerContextOptions = new DbContextOptionsBuilder<PlayerContext>();
    PlayerContextOptions.UseSqlServer(Configuration.GetConnectionString("Default"));
    services.AddSingleton(PlayerContextOptions.Options);

    services.AddDbContext<PlayerContext>(options => options.UseSqlServer(Configuration.GetConnectionString("Default")));



    services.AddCors(options => options.AddPolicy("CorsPolicy",
        builder =>
        {
            builder.AllowAnyMethod().AllowAnyHeader()
            .AllowCredentials();
            }));

    services.AddSignalR();
} 

但我根本不知道在我的Hub文件中该怎么做。我甚至不知道从哪里开始。我添加了单例,但我不知道如何在我的集线器文件中访问它。这就是我想做的事情,但我愿意采取更好的方式:

MyHub.cs

using (PlayerContext dbContext = new PlayerContext(/* Singleton needs to go here */))
{
    // do database stuff
} 

4 个答案:

答案 0 :(得分:4)

使用对SignalR集线器的依赖项注入来注入EF DbContext是错误的选择,因为SignalR集线器本身是Singleton,并且不应与生命周期较短的依赖项相关,因此您最终会得到警告。这意味着,您不能使用PerRequest / Transient生存期作用域来注册DbContext,而只能使用Singleton。将DbContext注册为Singleton是一个非常糟糕的选择。创建新上下文并不昂贵,但是具有单例上下文的中心将在一段时间后成倍增长。

我建议将DbContextFactory用于Hub类,在您的Hub中,从工厂询问新的DbContext并将其放入using语句。您还可以将工厂本身注册为Singleton,并更加清楚集线器构造函数中的依赖性。

using (var dbContextScope = dbContextScopeFactory.Create(options))
{
    //do database stuff
    dbContextScope.SaveChanges();
}

答案 1 :(得分:2)

您必须将您的DBContext添加到DI,以便从Hub的构造函数中获取它。

public class MyHub
{
      private PlayerContext dbContext;

      public MyHub(PlayerContext dbContext)
      {
           this.dbContext = dbContext;
      }

      public void YourMethod()
      {
           //call the dbContext here by Dot Notaition
      }
}

答案 2 :(得分:0)

似乎仍未记录访问范围服务的信息。但是查看源代码,我们可以看到DefaultHubDispatcherevery invocation创建了作用域和中心实例。这意味着我们可以像在DbContext控制器中那样使用asp.net core和其他范围服务。

新的DbContext实例在每次调用集线器方法时都会注入到集线器构造函数中。调用完成后,DbContext被处置。

Startup.cs:

services.AddDbContext<PlayerContext>(
    options => { options.UseSqlServer(Configuration.GetConnectionString("Default")); },
    ServiceLifetime.Scoped
);

集线器:

public class PlayerHub
{
    private readonly PlayerContext _dbContext;
    public PlayerHub(PlayerContext dbContext)
    {
       _dbContext = dbContext;
    }
    // using _dbContext 
}

答案 3 :(得分:0)

这在带有 Entity Framework Core 和 SignalR 的 .net Core 3.1 中对我有用。我没有在启动时添加任何东西(实际上在 3.1 中默认启动中没有包含连接服务)。一切都在中心和 appsettings.json 中完成。

应用设置:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "ConStr": "Data Source=.\\sqlexpress;Initial Catalog=ReactUserTasks;Integrated Security=true;"
  }
}

中心: 调用在 appsettings 中设置的“ConStr”连接。

public class MyHub : Hub
{
    private string _conn;

    public MyHub(IConfiguration configuration)
    {
        _conn = configuration.GetConnectionString("ConStr");
    } 

然后在 MyHub 中设置使用连接的方法。

public List<Items> GetTasks()
{
    var db = new ItemRepository(_conn);
    return db.GetTasks();
}