2

У меня есть приложение Asp.net 5/Core 1 с EF7. Обычно я регистрирую DbContext в контейнере DI.Как использовать инъецированный DbContext в параллельных методах в ядре asp.net и ef7?

services.AddEntityFramework().AddSqlServer() 
    .AddDbContext<MyDbContext>(options => options.UseSqlServer(connection)); 

Вот небольшой пример, показывающий, что я пытаюсь сделать.

public class MyController : Controller 
{ 
    MyDbContext _myDbContext; 

    public MyController(MyDbContext myDbContext) 
    { 
     _myDbContext = myDbContext; 
    } 

    public IActionResult Index() 
    { 
     //Just start these and don't wait for them to finish 
     //We don't care if they succeed or not 
     Task.Run(() => DoSomeLogging1()); 
     Task.Run(() => DoSomeLogging2()); 

     return View(); 
    } 

    private void DoSomeLogging1() 
    { 
     _myDbContext.Items.ToList(); 
    } 

    private void DoSomeLogging2() 
    { 
     _myDbContext.Items.ToList(); 
    } 
} 

Оба метода DoSomeLoggingX будет использовать экземпляр MyDbContext, который был впрыскиваемого к контроллеру. Поскольку методы запускаются одновременно с выполнением запросов db в одно и то же время, другой будет неизменно терпеть неудачу с

Соединение не было закрыто. Текущее состояние подключения - .

MyDbContext также использует DI для получения некоторых ссылок, поэтому я не могу использовать его напрямую, даже если бы захотел.

Как я могу запускать код параллельно и все еще иметь возможность использовать мою базу данных через сущность framework?

+0

Можете ли вы показать код всего вашего действия? Кажется, что вы не дождались завершения задачи. – Thomas

+3

Прежде всего, не создавайте потоки фона в ASP.NET, это очень плохая практика. Для приложений ASP.NET потоки являются наиболее важным ресурсом, который у вас есть. Если вы выполняете операции async, вы должны использовать await/async, это освобождает поток до тех пор, пока операция async не будет выполнена. Если у вас есть чувствительные к ЦП операции, выполняйте их в строке ** Запросить поток **, не запускайте для нее новую. DbContexts в ASP.NET регистрируются по умолчанию по умолчанию, это означает, что они будут разрешаться и жить на протяжении всего запроса. Когда запрос заканчивается, они будут удалены. – Tseng

+1

Если вы действительно хотите выполнить некоторую регистрацию и немедленно вернуться, вам нужно использовать какую-то шину сообщений, в которой вы запускаете события журнала, и они попадают в очередь на шине сообщений и обрабатываются некоторой службой, которая имеет dbcontext, который имеет более длительный срок службы (т. е. продолжительность жизни приложения), и выполняйте обработку журнала там, или если вы используете распределенную архитектуру (rabbitmq или другую систему AMQP) и имеете отдельный процесс, получите сообщения из очереди и обработайте их. – Tseng

ответ

1

Я также столкнулся с этой проблемой, и сейчас я использую свои временные раствор EF 7 (Core). Create DBContext like AddTransient

Если кто-то может предоставить более элегантное решение, я буду признателен. Иногда мне действительно нужно возвращать мгновенный результат пользователю, и в таких случаях ждать/асинхронно не подходит

0

Простой ответ: вы не можете. EF не предназначен для параллельного выполнения sql (и никогда не будет, я думаю).

Простой ответ. Вероятно, это не правильный подход к решению вашей проблемы (@Tseng сделал точку в своих комментариях), но если вам нужно сделать протоколирование таких вещей, как, что вы можете:

  • сделать последовательное действие два протоколирования и доли тот же экземпляр EF
  • использовать обычный старый SQL с объектом SqlConnection (который прекрасно работает с параллельной обработкой) - и это быстрее
  • использовать рамки протоколирования как NLog, которая поддерживает журнал и забыть подход
Смежные вопросы