c# - 如何在类/单独的线程 ASP.Net Core 中使用 ApplicationDbContext
问题描述
我试图让一个单独的线程启动一个循环过程,以从 api 调用收集和导入数据并将其插入本地数据库。我尝试以与在控制器中相同的方式创建数据库连接,但它不断给我各种错误。
我尝试了多种方法。对于下面的设置,它给了我这个错误:
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");
}
尽管您可能希望从配置中读取连接字符串。
推荐阅读
- sql - 在 SQL Server 2017 中添加新列并将 GETDATE 设置为值
- moodle - Moodle 规则类型
- python - 唯一导入 * 只允许在模块级别
- java - 将由ArrayList的数字和单词组成的String转换为int java
- python - Python:是否有一个循环函数来总结这一点?
- mongodb - Mongo DB搜索查询不给出结果
- niagara-4 - 如何在 Niagara-4 中获取站点正常运行时间(开始时间)信息?
- api - 什么是合适的 woo-commerce API 来创建带有归属的订单
- c++ - 在 std::qsort 的比较函数中处理错误情况
- ruby - IO.pipe 上的 Ruby readpartial 不会引发 EOFError