ASP.NET MVC: лучший способ вызова хранимой процедуры
Я пытаюсь решить, какой из них лучше всего вызвать хранимую процедуру.
Я новичок в ASP.NET MVC, и я много читал о Linq to SQL и Entity Framework, а также о шаблоне репозитория. Честно говоря, мне трудно понять реальные различия между L2S и EF... но я хочу убедиться, что то, что я создаю в своем приложении, является правильным.
В настоящее время мне нужно правильно вызвать хранимые процедуры, чтобы: a) сохранить некоторую пользовательскую информацию и получить ответ и, б) захватить некоторое портирование для каталога продуктов.
До сих пор я создал файл Linq to SQL.dbml, выбрал sotred процедуру из Server Explorer и перетащил этот экземпляр в .dbml. В настоящее время я вызываю хранимую процедуру следующим образом:
MyLinqModel _db = new MyLinqModel();
_db.MyStoredProcedure(args);
Я знаю, что нужно быть более вовлеченным... плюс я делаю это в своем контроллере, который, как я понимаю, не является хорошей практикой.
Может ли кто-нибудь узнать, что мои проблемы здесь?
Ответы
Ответ 1
LINQ и EF, вероятно, будут излишними, если все, что вы пытаетесь сделать, это вызвать хранимую процедуру.
Я использую Enterprise Library, но ADO.NET также отлично работает.
См. этот учебник.
Кратко (бесстыдно скопировано и вставлено из ссылки):
SqlConnection conn = null;
SqlDataReader rdr = null;
// typically obtained from user
// input, but we take a short cut
string custId = "FURIB";
Console.WriteLine("\nCustomer Order History:\n");
// create and open a connection object
conn = new SqlConnection("Server=(local);DataBase=Northwind; Integrated Security=SSPI");
conn.Open();
// 1. create a command object identifying
// the stored procedure
SqlCommand cmd = new SqlCommand(
"CustOrderHist", conn);
// 2. set the command object so it knows
// to execute a stored procedure
cmd.CommandType = CommandType.StoredProcedure;
// 3. add parameter to command, which
// will be passed to the stored procedure
cmd.Parameters.Add(
new SqlParameter("@CustomerID", custId));
// execute the command
rdr = cmd.ExecuteReader();
// iterate through results, printing each to console
while (rdr.Read())
{
Console.WriteLine(
"Product: {0,-35} Total: {1,2}",
rdr["ProductName"],
rdr["Total"]);
}
}
Обновление
Я пропустил ту часть, где вы сказали, что делаете это в своем контроллере.
Нет, это не правильный способ сделать это.
Ваш контроллер должен быть задействован только для создания структуры представления. Создайте отдельную библиотеку классов под названием "Уровень доступа к данным" или нечто более общее, и создайте класс, который обрабатывает вызовы ваших сохраненных процессов, создавая объекты из результатов и т.д. Существует много мнений о том, как это следует обрабатывать, но, возможно, наиболее распространенным является:
View
|
Controller
|
Business Logic
|
Data Access Layer
|--- SQL (Stored procs)
-Tables
-Views
-etc.
|--- Alternate data sources
-Web services
-Text/XML files
-blah blah blah.
MSDN имеет достойный учебник по этой теме.
Ответ 2
Попробуйте следующее:
Чтение:
var authors = context.Database.SqlQuery<Author>("usp_GetAuthorByName @AuthorName",
new SqlParameter("@AuthorName", "author"));
Update:
var affectedRows = context.Database.ExecuteSqlCommand
("usp_CreateAuthor @AuthorName = {0}, @Email= {1}",
"author", "email");
Из этой ссылки: http://www.dotnetthoughts.net/how-to-execute-a-stored-procedure-with-entity-framework-code-first/
И я бы пошел с фреймворком, который Дэвид Лайвли упомянул, вместо того, чтобы иметь подпрограммы в контроллере. Просто передайте результаты как IEnumerable<blah>
из функции в отдельном классе репозитория для редактирования, передайте логическое значение назад, если обновление было выполнено для обновления.
Ответ 3
LINQ to SQL и ADO.NET EF присоединяют чтение хранимых procs к классу контекста данных/объектов, который вы используете, чтобы идти против его различных объектов. Для создания, обновления и удаления вы можете создать proc, который отображает свойства объекта, который генерирует модель, и используя окно сопоставления сущностей (забудьте точное имя прямо сейчас), вы можете сопоставить поля объектов с параметрами proc, Итак, скажем, у вас есть таблица Customers, EF генерирует объект Customer, и вы можете сопоставить параметры proc с свойствами объекта Customer при попытке обновить/вставить/удалить.
Теперь вы можете сопоставить CUD proc с функцией, но я не знаю всех последствий; Мне нравится, как я только что упомянул лучшее.
НТН.
Ответ 4
Я использую общий шаблон, чтобы передать интерфейс репозитория в ваш контроллер путем инъекции зависимостей. Выбор той технологии persistence/orm, которую вы используете, действительно является другой проблемой и не связан с тем, что вы используете MVC. Использование шаблона репозитория и кодирования для абстракций (интерфейсов) упрощает проверку вашего приложения путем издевательства над вашими репозиториями.
Я думаю, вы также должны попытаться использовать как можно меньше хранимых процедур. Это означает, что вы можете более легко протестировать свою логику изолированно (модульные тесты) без необходимости подключения к базе данных. Я очень рекомендую посмотреть NHibernate. Кривая обучения довольно крутая, но вы полностью контролируете свои сопоставления и настройки. Есть очевидные случаи, когда вам понадобятся хранимые процедуры для повышения производительности, но использование ORM преимущественно очень полезно.
Ответ 5
Я не могу представить, что ваша цель - вызвать хранимую процедуру. Мне кажется, что вам нужно забыть хранимые процедуры и использовать Linq to Sql. Я говорю L2S, потому что EF гораздо больше, чтобы учиться, и не нужен в этом случае.