簡體   English   中英

如何在類/單獨線程ASP.Net Core中使用ApplicationDbContext

[英]How to use ApplicationDbContext in a Class / Separate Thread ASP.Net Core

我試圖讓一個單獨的線程啟動循環過程,以從api調用中收集和導入數據並將其插入本地db。 我嘗試以與在控制器中相同的方式創建數據庫連接,但是它不斷給我帶來各種錯誤。

我嘗試了多種方法。 對於下面的設置,它給了我這個錯誤:

System.ObjectDisposedException:'無法訪問已處置的對象。 導致此錯誤的常見原因是,處理從依賴項注入中解決的上下文,然后稍后嘗試在應用程序中的其他位置使用相同的上下文實例。 如果在上下文上調用Dispose()或將上下文包裝在using語句中,則可能會發生這種情況。 如果您正在使用依賴項注入,則應讓依賴項注入容器來處理上下文實例。

該設置用於測試目的。

public class HomeController : Controller
{
    public ApplicationDbContext db;

    public HomeController(ApplicationDbContext context)
    {
        db = context;
    }
    public IActionResult Index()
    {
        // This executes the code and inserts the test row no problem.
        BinanceData binanceData = new BinanceData();
        binanceData.Symbol = "Test";
        binanceData.RealTime = DateTime.Now;
        db.BinanceData.Add(binanceData);
        db.SaveChanges();
        // End

        // Where I create the new thread and start the process
        Thread doThis = new Thread(delegate ()
        {
            DataCollection dataCollection = new DataCollection(db);
            dataCollection.InsertData(DateTime.Now);
        });
        doThis.Start();
        // End

        return View();
    }

這是我嘗試創建連接(或通過現有連接)並開始循環和收集/插入數據的類。

    public class DataCollection
{
    public ApplicationDbContext db;

    public DataCollection(ApplicationDbContext context)
    {
        db = context;
    }
    public void InsertData(DateTime nextTime)
    {
        List<string> tokens = new List<string> { "ETHBTC", "LTCBTC", "BNBBTC", "NEOBTC", "GASBTC", "BTCUSDT", "MCOBTC", "WTCBTC", "LRCBTC", "QTUMBTC", "YOYOBTC", "OMGBTC", "ZRXBTC", "STRATBTC", "SNGLSBTC", "BQXBTC", "KNCBTC", "FUNBTC", "SNMBTC", "IOTABTC", "LINKBTC", "XVGBTC", "SALTBTC", "MDABTC", "MTLBTC", "SUBBTC", "EOSBTC", "SNTBTC", "ETCBTC", "MTHBTC", "ENGBTC", "DNTBTC", "ZECBTC", "BNTBTC", "ASTBTC", "DASHBTC", "OAXBTC", "BTGBTC", "EVXBTC", "REQBTC", "VIBBTC", "TRXBTC", "POWRBTC", "ARKBTC", "XRPBTC", "MODBTC", "ENJBTC", "STORJBTC", "KMDBTC", "RCNBTC", "NULSBTC", "RDNBTC", "XMRBTC", "DLTBTC", "AMBBTC", "BATBTC", "BCPTBTC", "ARNBTC", "GVTBTC", "CDTBTC", "GXSBTC", "POEBTC", "QSPBTC", "BTSBTC", "XZCBTC", "LSKBTC", "TNTBTC", "FUELBTC", "MANABTC", "BCDBTC", "DGDBTC", "ADXBTC", "ADABTC", "PPTBTC", "CMTBTC", "XLMBTC", "CNDBTC", "LENDBTC", "WABIBTC", "TNBBTC", "WAVESBTC", "GTOBTC", "ICXBTC", "OSTBTC", "ELFBTC", "AIONBTC", "NEBLBTC", "BRDBTC", "EDOBTC", "WINGSBTC", "NAVBTC", "LUNBTC", "APPCBTC", "VIBEBTC", "RLCBTC", "INSBTC", "PIVXBTC", "IOSTBTC", "STEEMBTC", "NANOBTC", "VIABTC", "BLZBTC", "AEBTC", "NCASHBTC", "POABTC", "ZILBTC", "ONTBTC", "STORMBTC", "XEMBTC", "WANBTC", "WPRBTC", "QLCBTC", "SYSBTC", "GRSBTC", "CLOAKBTC", "GNTBTC", "LOOMBTC", "REPBTC", "TUSDBTC", "ZENBTC", "SKYBTC", "CVCBTC", "THETABTC", "IOTXBTC", "QKCBTC", "AGIBTC", "NXSBTC", "DATABTC", "SCBTC", "NPXSBTC", "KEYBTC", "NASBTC", "MFTBTC", "DENTBTC", "ARDRBTC", "HOTBTC", "VETBTC", "DOCKBTC", "POLYBTC", "PHXBTC", "HCBTC", "GOBTC", "PAXBTC", "RVNBTC", "DCRBTC", "USDCBTC", "MITHBTC", "BCHABCBTC" };

        foreach (string token in tokens)
        {
            BinanceData binance = new BinanceData();
            using (var client = new BinanceClient())
            {
                var data = client.GetKlines(token, Binance.Net.Objects.KlineInterval.OneMinute, null, null, 2);
                var kline = data.Data[0];
                binance.Symbol = token;
                binance.Close = kline.Close;
                binance.CloseTime = kline.CloseTime;
                binance.High = kline.High;
                binance.Low = kline.Low;
                binance.Open = kline.Open;
                binance.OpenTime = kline.OpenTime;
                binance.QuoteAssetVolume = kline.QuoteAssetVolume;
                binance.TakerBuyBaseAssetVolume = kline.TakerBuyBaseAssetVolume;
                binance.TakerBuyQuoteAssetVolume = kline.TakerBuyQuoteAssetVolume;
                binance.TradeCount = kline.TradeCount;
                binance.Volume = kline.Volume;
                binance.RealTime = DateTime.Now;
            }
        db.BinanceData.Add(binance);
        db.SaveChanges();
        }
        CountUntilNextMin(nextTime);
    }

    public void CountUntilNextMin(DateTime nextTime)
    {
        while (DateTime.Now < nextTime)
        {
            System.Threading.Thread.Sleep(10000);
        }
        DateTime passTime = DateTime.Now.AddMinutes(1);
        InsertData(passTime);
    }
}

這是我的ApplicationDbContext類

    public class ApplicationDbContext : IdentityDbContext
{
    public DbSet<ApplicationUser> ApplicationUsers { get; set; }
    public DbSet<BinanceData> BinanceData { get; set; }
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    public ApplicationDbContext()
        : base()
    {
    }
}

還有我的StartUp.cs ConfigureServices方法

        public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddIdentity<IdentityUser, IdentityRole>()
            .AddDefaultUI()
            .AddDefaultTokenProviders()
            .AddEntityFrameworkStores<ApplicationDbContext>();

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

默認情況下,您的DI容器將DbContext限定在請求中。 如果您想在長時間運行的后台進程中使用它,只需直接創建它即可。 例如:

Thread doThis = new Thread(delegate ()
{
    using (var db = new ApplicationDbContext())
    {
      DataCollection dataCollection = new DataCollection();
      dataCollection.InsertData(DateTime.Now);
    }
});

將需要配置DbContext,最簡單的方法是重寫OnConfiguring以連接到數據庫。 至少像這樣:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
      optionsBuilder.UseSqlServer("Server=YourServer;Database=YourDatabase;Trusted_Connection=True;MultipleActiveResultSets=true");
}

盡管您可能想從配置中讀取連接字符串。

我通過調用CreateScope來使用它

public static async Task InitializeDatabaseAsync(IServiceProvider serviceProvider, IHostingEnvironment env)
{
    var result = false;

    using (var scope1 = serviceProvider.CreateScope())
    using (var db1 = scope1.ServiceProvider.GetService<MainContext>())
    {
         result = await db1.Database.EnsureCreatedAsync();
        if (result)
        {

            InsertTestData(serviceProvider, env);
        }
    }
}

然后

using (var scope = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
using (var db = scope.ServiceProvider.GetService<MainContext>())
{
    existingData = db.Set<TEntity>().ToList();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM