Я пытаюсь выяснить, почему мой контекст БД опровергается с помощью кода ниже.Я пытаюсь обновить статус записи на этом этапе обработки, но получаю исключение при попытке сохранить изменения в поле состояния объекта htis.
Не имеет значения, если я использую асинхронные или не асинхронные методы для вызовов .SaveChanges () или .FirstOrDefault ().
Это зарегистрировано для запуска IHostedService
IHostedService:
public class HostedDaemon : IHostedService
{
private readonly ILogger<HostedDaemon> _logger;
private Timer _queueTimer;
private Timer _runTimer;
private IServiceProvider Services { get; set; }
public HostedDaemon(IServiceProvider services, ILogger<HostedDaemon> logger)
{
Services = services;
_logger = logger;
}
public Task StartAsync(CancellationToken cancellationToken)
{
var queueAutoEvent = new AutoResetEvent(false);
_logger.LogInformation("HostedDaemon Starting");
_queueTimer = new Timer(QueueJobs, queueAutoEvent, TimeSpan.Zero,
TimeSpan.FromSeconds(900));
_runTimer = new Timer(RunQueuedJobs, queueAutoEvent, TimeSpan.Zero,
TimeSpan.FromSeconds(10));
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("HostedDaemon Stopping");
_queueTimer?.Change(Timeout.Infinite, 0);
_runTimer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
_queueTimer?.Dispose();
_runTimer?.Dispose();
}
private void QueueJobs(object stateInfo)
{
using (var scope = Services.CreateScope())
{
var autoEvent = (AutoResetEvent)stateInfo;
var daemonProcessing = scope.ServiceProvider.GetRequiredService<IDaemonService>();
//daemonProcessing.QueueJob();
//daemonProcessing.RunJob();
autoEvent.Set();
}
}
private void RunQueuedJobs(object stateInfo)
{
using (var scope = Services.CreateScope())
{
var autoEvent = (AutoResetEvent)stateInfo;
var daemonProcessing = scope.ServiceProvider.GetRequiredService<IDaemonService>();
//daemonProcessing.QueueJob();
daemonProcessing.RunJob();
autoEvent.Set();
}
}
}
Фоновая служба:
public async Task RunJob()
{
try
{
_logger.LogInformation("Starting transaction processing");
//TODO: Hook up SP
var nextQueuedJob = _context.Transaction
.Where(x => x.TransactionStatusId == (int) TransactionStatus.Queued).OrderBy(x => x.QueuedTime)
.Include(x => x.BrokerageData).FirstOrDefault();
if (nextQueuedJob != null)
{
nextQueuedJob.TransactionStatusId = (int)TransactionStatus.ProcessingData;
_context.Transaction.Update(nextQueuedJob);
//await _context.SaveChangesAsync();
var brokerageData = nextQueuedJob.BrokerageData.FirstOrDefault();
var order = JsonConvert.DeserializeObject<OrderShort>(brokerageData.BrokerageContent);
var dynamicsSalesOrder = await CreateNewSalesOrderShort(order);
var salesOrderLines = new List<SalesOrderLineShort>();
foreach (var orderItem in order.Items)
{
var unitPrice = (orderItem.SubTotal + orderItem.Tax)/orderItem.Quantity;
var salesOrderLine = new SalesOrderLineShort
{
ItemId = new Guid("42dd99ff-7133-41f7-88c5-81f922ef77dd"),
LineType = "Item",
Description = orderItem.ProductDescription,
UnitOfMeasureId = new Guid("cab0928b-e7af-4bd6-923f-3706b4761681"),
UnitPrice = unitPrice,
DiscountAmount = orderItem.CouponDiscountAmount,
Quantity = orderItem.Quantity,
TaxCode = "DEV"
};
salesOrderLines.Add(salesOrderLine);
}
nextQueuedJob.TransactionStatusId = (int)TransactionStatus.ProcessingComplete;
await _context.SaveChangesAsync();
nextQueuedJob.TransactionStatusId = (int)TransactionStatus.ReadyForTransfer;
//TOOO: hook into reconciliation tables to commit an update
nextQueuedJob.TransactionStatusId = (int)TransactionStatus.TransferringData;
foreach (var salesOrderLine in salesOrderLines)
{
await _requestClient.PostRequest(
$"https://api.businesscentral.dynamics.com/v1.0/afff8eda-37c9-4c72-833b-a36dc6c8d5df/api/beta/companies/c7fdd45d-617d-47b3-adbe-7c0c69c21dd1/salesOrders/{dynamicsSalesOrder.Id}/salesOrderLines",
salesOrderLine);
}
nextQueuedJob.TransactionStatusId = (int)TransactionStatus.TransferComplete;
nextQueuedJob.TransactionStatusId = (int)TransactionStatus.ReadyForValidation;
nextQueuedJob.TransactionStatusId = (int)TransactionStatus.ValidatingOriginData;
var query = new CrmQuery();
query.UpdateOrderStatus(order.SalesOrderId, CrmQuery.OrderFIStatus.Completed,
order.FI_LastModified);
nextQueuedJob.TransactionStatusId = (int)TransactionStatus.TransactionCompleted;
}
}
catch (Exception e)
{
_logger.LogError($"exception occurred while running job.\n{e.InnerException}");
}
}
Исключение:
Message "Cannot access a disposed object. A common cause of this error
is disposing a context that was resolved from dependency injection and then
later trying to use the same context instance elsewhere in your
application.
This may occur if you are calling Dispose() on the context, or wrapping the
context in a using statement. If you are using dependency injection, you
should let the dependency injection container take care of disposing context
instances.\r\nObject name: 'FisEntities'." string
Конфигурация запуска:
public void ConfigureServices(IServiceCollection services)
{
DynamicsAccountGuid = Configuration["Services:Dynamics:AccountGuid"];
DynamicsCompany = Configuration["Services:Dynamics:Companies:Development"];
DynamicsBasicAuth = Configuration["Services:Dynamics:BasicAuth"];
ConnectionString = Configuration["ConnectionStrings:FIS_Local"];
services.AddSingleton(Configuration);
services.AddEntityFrameworkSqlServer()
.AddDbContext<FisEntities>(options => options.UseSqlServer(ConnectionString));
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.AddHttpClient<IRequestClient, DynamicsClient>("dynamics", d =>
{
d.BaseAddress = new Uri($"https://api.businesscentral.dynamics.com/v1.0/{DynamicsAccountGuid}/api/beta/companies/{DynamicsCompany}");
d.DefaultRequestHeaders.Add("Authorization", DynamicsBasicAuth);
});
services.AddTransient<IQueueClient, CrmClient>();
services.AddHostedService<HostedDaemon>();
services.AddScoped<IDaemonService, TransactionService>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}