У нас есть контроллер, где пользователи могут представить любое количество адресов электронной почты, чтобы пригласить других (потенциальные) членов в качестве друзей. Если адрес не найден в базе данных, мы отправляем сообщение E-Mail этому пользователю. Поскольку пользователю не нужно ждать завершения этого процесса, чтобы продолжить работу, это выполняется асинхронно.Запись в БД после контроллера была захоронена
Отправка электронных писем может занять много времени, если серверы будут реагировать медленно, вниз или перегружены. Отправитель E-Mail должен обновить базу данных в соответствии с состоянием, полученным с сервера электронной почты, так что, например, установка запроса друга в состояние «Ошибка», когда происходит постоянный сбой, например, если адрес не существует. Для этой цели компонент E-Mail реализует функцию SendImmediateAsync(From,To,Subject,Content,Callback,UserArg)
. После того, как сообщение было доставлено (или оно не выполнено), Callback вызывается с определенными аргументами о состоянии доставки.
Когда он в конечном итоге вызывает делегата, объект DbContext уже удален (поскольку контроллер был слишком), и я не могу вручную создать новый, используя new ApplicationDbContext()
, потому что нет конструктора, который принимает строку подключения.
Вопрос
Как я могу писать в базу данных долго после того, как контроллер был расположен? Я еще не понял, как вручную создать объект DbContext
для себя. Объект типа ApplicationDbContext
передается конструктору контроллера, и я надеялся, что смогу создать его для себя, но у конструктора нет аргументов, которые я могу предоставить (например, строка подключения). Я хочу избегать вручную создавать SQL-соединение и собирать инструкции INSERT вручную и предпочел бы работать с уже созданной моделью сущности.
Код
код показывает пораженный сегмент только без каких-либо проверок ошибок для удобства чтения.
[Authorize]
public class MembersController : Controller
{
private ApplicationDbContext _context;
public MembersController(ApplicationDbContext context)
{
_context = context;
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Friends()
{
MailHandler.SendImmediateAsync(FROM,TO,SUBJECT,CONTENT,
delegate (Guid G, object any)
{
//THIS IS NOT WORKING BECAUSE _context IS DISPOSED
var ctx = _context;
Guid Result = (Guid)any; //user supplied argument
if (G != Guid.Empty)
{
ctx.MailConfirmation.Add(new MailConfirmation()
{
EntryId = Result,
For = EntryFor.FriendRequest,
Id = G
});
if (G == MailHandler.ErrorGuid)
{
var frq = _context.FriendRequest.SingleOrDefault(m => m.Id == Result);
frq.Status = FriendStatus.Error;
ctx.Update(frq);
}
ctx.SaveChanges();
}
}, req.Id);
//rendering view
}
}
Такой вид работы. Проблема заключается в том, что я не могу изменить «ApplicationDbContext» для наследования из DbContext или разрывов сайта по какой-либо причине. Я закончил это: создайте «AsyncDbContext», который в основном имеет тот же контент, что и «ApplicationDbContext», но наследует от «DbContext». Затем я сменил конструктор моего контроллера-члена на: 'public MembersController (DbContextOptions options, ApplicationDbContext context)', потому что я до сих пор не могу вручную создать экземпляр AppicationDbContext. Таким образом, я получаю оба. Контекст для запроса и объекта options для асинхронных контекстов. –
AyrA
Что наследует ваше определение ApplicationDbContext? – natemcmaster
ef создает его как «открытый класс ApplicationDbContext: IdentityDbContext' –
AyrA