Access DB context through SignalR Core

女生的网名这么多〃 提交于 2020-01-21 09:19:25

问题


I'm using AspNetCore.SignalR and I need advice on how to access my SQL Server database through my Hub. There are not a lot of resources out there about this. I know how to add a singleton but I do not know how to access it later. How can I access a DB context that is defined using a Configuration.GetConnectionString in Startup.cs inside my Hub's Tasks?

Thanks.

Here's the relevant code:

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();
} 

But I don't know what to do in my Hub file at all. I don't even know where to start. I added the singleton but I don't know how to access it in my hub file. This is what I would like to do, but I'm open to a better way of doing it:

MyHub.cs

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

回答1:


You have to add your DBContext to DI so you can get it from the Constructor of your 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:


Using the dependency injection on SignalR hub's to inject EF DbContext is a wrong choice, because SignalR hub itself is a Singleton and shouldn't have dependencies with the lower lifetime cycle, you will end up with a warnings. That means, that you cant register your DbContext with PerRequest/Transient lifetime scopes, only with singleton. Registering DbContext as Singleton is a very bad choice. Making new context isn't expensive, but your hub with a singleton context will grow exponentially after some time.

I suggest using the DbContextFactory for the Hub classes, in your hub ask the new DbContext from the factory and put it to the using statement. You could also register factory itself as a Singleton and make dependency in hub constructor more clear.

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



回答3:


Seems like accessing scoped services still is not documented. But looking to the source code we can see that DefaultHubDispatcher creates scope and hub instance on an every invocation. It means we can use DbContext and other scoped services like we use to do it in asp.net core controllers.

New DbContext instance is injected into the hub constructor on every hub method invocation. When invocation is completed DbContext gets disposed.

Startup.cs:

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

Hub:

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


来源:https://stackoverflow.com/questions/50885626/access-db-context-through-signalr-core

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!