asp.net MVC — Как я могу совместно использовать один и тот же экземпляр SqlConnection через разные классы репозитория

#c# #asp.net-mvc #dependency-injection #asp.net-mvc-5 #repository-pattern

#c# #asp.net-mvc #внедрение зависимостей #asp.net-mvc-5 #репозиторий-шаблон

Вопрос:

Я создаю новый проект с использованием MVC5 и plain ADO.NET (просто в качестве учебного упражнения) и мне нужно создать репозиторий, который регистрирует модель с несколькими связанными объектами, которые также необходимо создать одновременно, и этим объектам, в свою очередь, может потребоваться вставить другие объекты.

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

Хотя это может показаться самым простым подходом, я не большой его поклонник, поэтому я хочу знать, есть ли какой-либо способ / обычная практика, которую я могу использовать для совместного использования одного и того же экземпляра SqlConnection, созданного для родительского объекта, с другими связанными объектами?

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

Редактировать

——————————-

Это репозиторий для родительского объекта (модели), который, я думаю, должен создать экземпляр SqlConnection и запустить транзакцию

  public class ModelRepository : IModelRepository
    {
        public int Add(Model entity)
        {
            using (var conn = new SqlConnection(ConnectionString))
            {   
                conn.Open();
                using (var command = conn.CreateCommand())
                {                    
                    command.Transaction = conn.BeginTransaction(IsolationLevel.ReadCommitted);
                    command.CommandText = "up_Model_Insert";
                    command.CommandType = CommandType.StoredProcedure;                 
                    

                    command.Parameters.Add(command.CreateParameter("@pName ", entity.Name));
                    command.Parameters.Add(command.CreateParameter("@pDescription", entity.Description));
                    //Other parameters...

                    //Call the repositories of the other objects

                    //....

                    //how can I make the other repositories use the same connection and 
                    //transaction as the Model entity?


                    

                    
                    return Convert.ToInt32(command.ExecuteScalar());
                }
            }
        }
    }
  

Проблема в том, что я не знаю, как заставить другие репозитории использовать то же соединение и транзакцию, что и объект «Model».

Я читал, что у Ninject есть эта концепция «области видимости объекта», но я не уверен, что было бы правильным в моем случае.

Комментарии:

1. вы заглядывали в IoC? он очень хорошо работает с MVC и, вероятно, был бы идеальным для внедрения зависимостей в вашем случае. Вот хорошая статья, которая помогает с IoC и MVC:

2. @skar в настоящее время я использую Ninject и то, что, как я думаю, известно как шаблон внедрения зависимостей конструктора. Проблема с этим шаблоном заключается в том, что, насколько я знаю, это выглядит так: всякий раз, когда мне нужен новый экземпляр класса X, перейдите и создайте все его зависимости, и для этого конкретного сценария это не то, что мне нужно, потому что будет несколько экземпляров класса SqlConnection .

3. вы должны иметь возможность зарегистрировать класс SqlConnection как одноэлементный в вашем контейнере IoC, что позволит вам создать экземпляр класса SqlConnection один раз и использовать тот же экземпляр, где он вам понадобится.

4. @skar Пожалуйста, посмотрите раздел Редактирования в моем вопросе.

Ответ №1:

Я не уверен, почему вы хотите «поделиться» соединением. Возвращаясь к основам, вы всегда должны инкапсулировать соединение в using блоке (предположим, вы используете EF).

Вам нужны транзакции, верно? Сейчас я просто думаю о своей голове: что вы могли бы сделать, так это обернуть вашу логику вставки в TransactionInfo классы. Эти TransactionInfo классы могут принимать an Action и репозиторий в качестве параметров. Действие в конечном итоге выполняет логику вставки одного объекта через данный репозиторий (репозиторий должен следовать некоторому интерфейсу, который предоставляет вам логику CRUD).

Когда у вас их несколько TransactionInfo , вы можете отправить их вместе куда-нибудь, что выполнит логику начала транзакции базы данных, выполнит все данные Actions из каждого TransactionInfo объекта и в конечном итоге выполнит транзакцию.

TransactionInfo может иметь такой конструктор, как:

 public TransactionInfo(Action action, ICrudRepository repository)
  

Надеюсь, я вас хорошо понял. Совместное использование an SqlConnection кажется мне неправильным.

Комментарии:

1. Пожалуйста, смотрите Раздел Редактирования в моем вопросе.