Пользовательское открытие / закрытие соединения для DbContext - PullRequest
3 голосов
/ 23 марта 2020

EF Core открывает и закрывает DbConnection для каждого запроса по умолчанию, если только вы не передаете уже открытое соединение.

У меня есть множество небольших запросов , поэтому вместо Открывая и закрывая соединение каждый раз, я хотел бы держать соединение открытым в течение пяти секунд за раз, одновременно используя это соединение для каждого запроса / команды. (Решение вопроса, связанного выше, оставляет соединение открытым в течение всего срока службы DBContext.)

Откладывая в сторону проблемы блокировки / параллелизма, куда я могу добавить нестандартные соединения, разрешающие / открывающие логи c в DbContext? Что-то вроде

before executing query:
   if connection is not open
      open
      set timer to fire close request in five seconds
   take lock on connection (to prevent closing)
      execute query
   release lock

Ответы [ 2 ]

2 голосов
/ 30 марта 2020

Это стандартный способ совершения транзакции. Вы можете комбинировать несколько запросов.

using (var context = new SchoolContext())
{
    var std = new Student()
    {
        FirstName = "Bill",
        LastName = "Gates"
    };
    context.Students.Add(std);

    // or
    // context.Add<Student>(std);

    context.SaveChanges();

   std = context.Students.First<Student>(); 
    std.FirstName = "Steve";
    context.SaveChanges();
}

ef Ядро может использовать одно и то же соединение или другое или основанное на пуле соединений. Ef ядро ​​подключил и отключил режим транзакции. Я думаю, что это может подойти вам. Сохранение данных в отключенном сценарии немного отличается от связанного сценария. В отключенном сценарии DbContext не знает об отключенных объектах, поскольку объекты были добавлены или изменены вне области действия текущего экземпляра DbContext. Таким образом, вам необходимо присоединить отключенные сущности к контексту с соответствующим EntityState для выполнения операций CUD (создание, обновление, удаление) с базой данных.

На следующем рисунке показаны операции CUD в отключенном сценарии:

Согласно приведенному выше рисунку, к DbContext необходимо присоединить несвязанные сущности (сущности, которые не отслеживаются DbContext) с соответствующим EntityState. Например, добавленное состояние для новых сущностей, измененное состояние для отредактированных сущностей и удаленное состояние для удаленных сущностей, что приведет к команде INSERT, UPDATE или DELETE в базе данных при вызове метода SaveChanges ().

Для вставки, обновления или удаления записей в таблице БД с использованием Entity Framework Core в отключенном сценарии необходимо выполнить следующие шаги:

Присоединить объект к DbContext с соответствующим EntityState, например, Добавлено, Изменено, или Deleted Call SaveChanges () метод В следующем примере демонстрируется вставка новой записи в базу данных с помощью описанных выше шагов:

//Disconnected entity
var std = new Student(){ Name = "Bill" };

using (var context = new SchoolContext())
{
    //1. Attach an entity to context with Added EntityState
    context.Add<Student>(std);

    //or the followings are also valid
    // context.Students.Add(std);
    // context.Entry<Student>(std).State = EntityState.Added;
    // context.Attach<Student>(std);

    //2. Calling SaveChanges to insert a new record into Students table
    context.SaveChanges();
}

В приведенном выше примере std является отключенным экземпляром сущности Student. Метод context.Add () присоединяет сущность Student к контексту с состоянием Added. Метод SaveChanges () создает и выполняет следующую инструкцию INSERT:

exe c sp_execute sql N'SET NOCOUNT ON; https://www.entityframeworktutorial.net/efcore/saving-data-in-disconnected-scenario-in-ef-core.aspx Это важные методы.

public DbContext(DbConnection existingConnection, bool contextOwnsConnection)
public DbContext(DbConnection existingConnection, DbCompiledModel model, bool contextOwnsConnection)

Поведение в EF6 и будущих версиях Для EF6 и будущих версий мы приняли подход, который, если вызывающий код решит открыть соединение с помощью вызывая context.Database.Connection.Open (), тогда у него есть веская причина для этого, и фреймворк будет считать, что ему нужен контроль над открытием и закрытием соединения, и больше не будет закрывать соединение автоматически.

Примечание

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

Мы также обновили код, чтобы ObjectContext.Connection.State теперь отслеживал состояние базовое соединение правильно.

  using System;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Core.EntityClient;
using System.Data.Entity.Infrastructure;

namespace ConnectionManagementExamples
{
    internal class DatabaseOpenConnectionBehaviorEF6
    {
        public static void DatabaseOpenConnectionBehavior()
        {
            using (var context = new BloggingContext())
            {
                // At this point the underlying store connection is closed

                context.Database.Connection.Open();

                // Now the underlying store connection is open and the
                // ObjectContext.Connection.State correctly reports open too

                var blog = new Blog { /* Blog’s properties */ };
                context.Blogs.Add(blog);
                context.SaveChanges();

                // The underlying store connection remains open for the next operation  

                blog = new Blog { /* Blog’s properties */ };
                context.Blogs.Add(blog);
                context.SaveChanges();

                // The underlying store connection is still open

           } // The context is disposed – so now the underlying store connection is closed
        }
    }
}

https://docs.microsoft.com/en-us/ef/ef6/fundamentals/connection-management?redirectedfrom=MSDN

0 голосов
/ 05 апреля 2020

В ADO. NET вы можете настроить пул соединений в соответствии с вашими требованиями

Пул соединений создается для каждой уникальной строки соединения. Когда пул создается, несколько объектов подключения создаются и добавляются в пул, так что требование минимального размера пула удовлетворяется. Соединения добавляются в пул по мере необходимости, вплоть до указанного максимального размера пула (по умолчанию 100). Соединения освобождаются обратно в пул, когда они закрываются или удаляются.

Диспетчер подключений удовлетворяет запросы на соединения, перераспределяя соединения, когда они возвращаются в пул. Если достигнут максимальный размер пула и доступное соединение недоступно, запрос помещается в очередь. Затем диспетчер пытается восстановить любые подключения до истечения времени ожидания (по умолчанию 15 секунд). Если диспетчер не может удовлетворить запрос до истечения времени ожидания подключения, возникает исключение.

Диспетчер подключений удаляет подключение из пула после того, как оно простаивает в течение приблизительно 4-8 минут, или если диспетчер обнаруживает что соединение с сервером было разорвано. Обратите внимание, что разорванное соединение может быть обнаружено только после попытки установить связь с сервером. Если обнаружено соединение, которое больше не подключено к серверу, оно помечается как недействительное. Недопустимые соединения удаляются из пула соединений только тогда, когда они закрыты или восстановлены.

Если SqlConnection выходит из области видимости, он не будет закрыт. Поэтому вы должны явно закрыть соединение, вызвав Close или Dispose. Close и Dispose функционально эквивалентны. Если значение пула соединений Pooling установлено на true или yes, базовое соединение возвращается обратно в пул соединений. С другой стороны, если для пула задано значение false или нет, базовое соединение с сервером фактически закрыто.

  using (SqlConnection connection = new SqlConnection("Integrated Security=SSPI;Initial Catalog=Northwind"))  
    {  
        connection.Open();
        // Pool A is created.  
    }  

using (SqlConnection connection = new SqlConnection("Integrated Security=SSPI;Initial Catalog=pubs"))  
    {  
        connection.Open();
        // Pool B is created because the connection strings differ.  
    }  

using (SqlConnection connection = new SqlConnection("Integrated Security=SSPI;Initial Catalog=Northwind"))  
    {  
        connection.Open();
        // The connection string matches pool A.  
    } 

Подробнее об этом можно прочитать в этой статье . , EF.Core и Connection pooling это

Связанный вопрос SO. Платформа сущностей и пул соединений

...