У меня есть приложение-функция Azure. Он получает много журналов в очереди хранилища. Каждый журнал представляет собой строку в базе данных Azure, состояние которой необходимо обновить. Поскольку функция App одновременно запускает множество экземпляров, может случиться так, что два экземпляра обновят одну и ту же строку, но в неправильном порядке. Поэтому мне нужно заблокировать определенную строку в базе данных, и если другой экземпляр попытается ее прочитать, ему придется дождаться освобождения строки. Лучше всего сделать это с помощью блокировки строк. Сможете ли вы добиться этого с помощью EF? Другие предложения тоже приветствуются.
Обратите внимание, что это не ядро EF, поэтому его необходимо поддерживать в стандартной версии.
public static class ProccesLogQueue
{
static SPOServiceConfiguration configuration = SPOServiceConfigurationManager.Get();
[FunctionName("ProccesLogQueue")]
public static void Run([QueueTrigger("log", Connection = "AMRStorageConnStr")]string logJson, TraceWriter log)
{
log.Info($"C# Queue trigger function processed: {logJson}");
var scanRepo = new ScanRepo(configuration.DBConnectionString);
var json = JObject.Parse(logJson);
var jobIdStr = json["JobId"].ToString();
var evnt = json["Event"].ToString();
var jobId = Guid.Parse(jobIdStr);
// start lock the row
var job = scanRepo.FindJob(jobId);
if (job == null)
{
log.Info("Job not found");
return;
}
if (job.Status == "JobEnd")
{
log.Info("Status allready JobEnd");
return;
}
job.Status = evnt;
job.Updated = DateTime.UtcNow;
scanRepo.UpdateJob(job);
// release the row
log.Info(DateTime.Now.ToString("hh:mm:ss"));
}
}
Вам нужно прочитать строку с помощью UPDLOCK, чтобы другие экземпляры не могли ее прочитать, пока вы не зафиксируете транзакцию. Так:
using (var tran = db.Database.BeginTransaction())
{
//for ef core
var job = db.Set<Job>().FromSqlInterpolated($"Select * from Jobs with (updlock) where JobId = {jobId}").First();
//for ef6 or ef core
//var job = db.Set<Job>().SqlQuery("Select * from Jobs with (updlock) where JobId = @jobId", jobId)
job.Status = 4;
db.SaveChanges();
tran.Commit();
}
Это EF Core и метод расширения в пространстве имен Microsoft.EntityFrameworkCore. learn.microsoft.com/en-us/ef/core/querying/raw-sql См. обновление для версии EF6.
Какую версию EF вы используете? У меня нет FromSqlInterpolated.