#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. Пожалуйста, смотрите Раздел Редактирования в моем вопросе.