我的 Blazor 應用程式遇到了一個奇怪的問題。該應用程式有一個后臺服務,可以輪詢遠程主機的狀態資訊,并使用該資訊更新資料庫。webasm 客戶端會看到后臺服務所做的任何更新,但如果我通過 API 控制器通過客戶端更新記錄(例如,更改 IP 地址),除非我重新啟動服務器,否則后臺服務不會看到新值。
以下是后臺服務的一些相關代碼:
public class Poller : BackgroundService
{
private readonly IServiceScopeFactory _scopeFactory;
private MyDbContext db;
public Poller(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
using (var scope = _scopeFactory.CreateScope())
{
db = scope.ServiceProvider.GetRequiredService<MyDbContext>();
// Main loop
while (!stoppingToken.IsCancellationRequested)
{
// Get list of workers
foreach (var worker in db.Workers
.Where(w => w.Status != WorkerStatus.Updating)
.ToList())
{
var prevStatus = worker.Status;
// Poll for new status
string currentStatus = await worker.PollAsync(stoppingToken);
if (currentStatus != null)
{
worker.Status = currentStatus;
}
if (worker.Status != prevStatus)
{
await Log(worker, $"Status changed to {worker.Status}", stoppingToken);
}
await db.SaveChangesAsync(stoppingToken);
}
}
}
}
private async Task Log(Worker? worker, string text, CancellationToken token)
{
var entry = new LogEntry
{
Worker = worker,
Text = text
};
db.LogEntries.Add(entry);
await db.SaveChangesAsync(token);
}
API 控制器的代碼是基本樣板:
[HttpPut("{id}")]
public async Task<IActionResult> PutWorker(string id, Worker worker)
{
if (id != worker.WorkerId)
{
return BadRequest();
}
_context.Entry(worker).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!WorkerExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
謝謝!
uj5u.com熱心網友回復:
只要您使用相同的 DbContext 實體,更新的資料將不會在您的物體中看到。
您可以查看此博客文章了解詳細資訊:
事實證明,Entity Framework 使用了 Identity Map 模式。這意味著一旦具有給定鍵的物體被加載到背景關系的快取中,只要該背景關系存在,它就永遠不會再次加載。因此,當我們第二次訪問資料庫以獲取客戶時,它從資料庫中檢索更新的 851 記錄,但由于客戶 851 已經加載到背景關系中,它忽略了資料庫中的更新記錄
http://codethug.com/2016/02/19/Entity-Framework-Cache-Busting/
我可以成功地重現這種行為。
對于您的情況,您可以選擇在每次迭代時創建一個新的背景關系實體
// Main loop
while (!stoppingToken.IsCancellationRequested)
{
using (var scope = _scopeFactory.CreateScope())
{
db = scope.ServiceProvider.GetRequiredService<MyDbContext>();
// Get list of workers
foreach (var worker in db.Workers
.Where(w => w.Status != WorkerStatus.Updating)
.ToList())
{
var prevStatus = worker.Status;
// Poll for new status
string currentStatus = await worker.PollAsync(stoppingToken);
if (currentStatus != null)
{
worker.Status = currentStatus;
}
if (worker.Status != prevStatus)
{
await Log(worker, $"Status changed to {worker.Status}", stoppingToken);
}
await db.SaveChangesAsync(stoppingToken);
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/497173.html
標籤:C# asp.net 核心 blazor-webassembly
上一篇:如何在EFCoreOnModelCreating(ModelBuildermodelBuilder)中生成錯誤訊息
