#c# #mysql #asp.net-mvc #dao
#c# #mysql #asp.net-mvc #dao
Вопрос:
Я хотел бы улучшить свой проект .NET, добавив еще один уровень при доступе к базе данных. Это мой код:
namespace Company.Models
{
public static class AgencyBean
{
[WebMethod]
[ScriptMethod(UseHttpGet = true)]
public static String createGUID(string name)
{
DataAccess dataAccess = new DataAccess();
bool exists = dataAccess.checkIfExists(Id);
if(exist)
{
dataAccess.delete(Id);
}
retur "ok";
}
}
}
Я поместил класс DataAccess в отдельную папку под названием «Помощники», и в ней содержится большинство моих запросов:
public class DataAccess
{
public bool checkIfExists(String Id)
{
try
{
SqlConnection cnn = new SqlConnection(dataConnection);
cnn.Open();
SqlCommand check_Id = new SqlCommand("SELECT COUNT(*) FROM TABLE_GUID WHERE ([USER_ID] = @Id)", cnn);
check_Id.Parameters.AddWithValue("@Id", Id);
int UserExist = (int)check_Id.ExecuteScalar();
if (UserExist > 0)
{
return true;
}
else
{
return false;
}
}
catch (SqlException ex)
{
Debug.WriteLine("SQL Exception " ex);
DisplaySqlErrors(ex);
throw ex;
}
}
}
public class AgentBeanController : Controller
{
// GET: AgentBean
public ActionResult Index(string name)
{
return View();
}
[AllowAnonymous]
[WebMethod]
public string AgentURL() //here we create Agent URL and return it to the view
{
string var = Models.AgentBean.createGUID("TODO");
return var;
}
}
Я получаю доступ к базе данных практически прямым способом. Как было бы с лучшей техникой, чтобы этот доступ мог быть более безопасным, например, доступ через уровень обслуживания?
Я подключаюсь к существующей базе данных sql на каком-либо сервере и работаю с архитектурой MVC в своем проекте.
Комментарии:
1. Вы на правильном пути. Если вы Загуглите термин «Хранилища данных» и «Внедрение зависимостей», это может продвинуть вас на шаг дальше. Общая идея репозитория заключается в том, что у вас есть отдельные классы на уровне модели для доступа к данным (как вы делаете сейчас), но они соответствуют интерфейсам. Когда вы создаете экземпляр своего класса AgencyBean, вы должны принять объект, который реализует этот интерфейс, в качестве аргумента. Преимущество заключается в том, что у вас может быть вторая реализация интерфейса, которая не затрагивает базу данных, используемую только для модульного тестирования. Инструмент DI, такой как Ninject, упрощает кодирование.
2. Теперь я понимаю это лучше, я также хотел внедрить модульное тестирование, и я вижу, что мне нужен DI. спасибо за совет!
Ответ №1:
Итак, вот что я делал в прошлом.
Во-первых, это ваше пространство имен «models»… модели никогда не должны иметь подключения к базе данных. Вместо этого у вас есть отдельный класс, такой как контроллер, который увлажняет некоторую модель.
Во-вторых, у меня был класс «service», который подключается к классу «repository». Класс репозитория реализует интерфейс для определения точного «типа» используемой вами базы данных.. но если это не входит в ваши требования, вам, вероятно, не нужно заходить так далеко.
В-третьих, найдите внедрение зависимостей (иначе DI). Существует несколько фреймворков. Лично я использовал Autofac, но существуют и другие, чтобы упростить работу.
В-четвертых, в ваших классах «контроллеры», «службы» и «ответственные» реализуйте внедрение зависимостей, а также любые интерфейсы, необходимые для формирования контракта.
В-пятых, я бы использовал фактическое пространство имен контроллера и не работал бы над вашим пространством имен моделей, чтобы продвигать http-вызовы band и далее…. Вместо этого создайте действие в своем классе контроллера и создайте экземпляр вашего «agencyBean», наполните его данными и верните эту модель в ваше представление.
По сути, в подобном сценарии вы пытаетесь заставить каждый компонент выполнять то, для чего он предназначен … разбивая обязанности на более мелкие части и сосредотачиваясь на этом. Ваш контроллер должен просто «извлекать» вашу модель и, возможно, выполнять некоторые преобразования по мере необходимости или любую другую логику бизнес-типа.
Ваша служба должна обрабатывать связь между вашим контроллером и уровнем базы данных.
Ваш уровень доступа к данным (т.Е., В данном случае, Некоторый класс «репозитория» …) будет выполнять все эти новые подключения к данным и / или настраивать вызовы хранимых процедур или запросов.
Выполнение этого способа имеет много преимуществ. Некоторые из основных — это удобство обслуживания, удобочитаемость, повторное использование кода. Конечно, это немного усложняет ваш проект с точки зрения размещения файлов где угодно… но это может быть и хорошо. Это намного лучше, чем объединять все в один класс и заставлять его делать все 🙂
Но, к вашему сведению, это из реализации, которую я делал в прошлом… Я уверен, что есть лучшие способы, но эта настройка сработала достаточно хорошо для моей команды и меня.
Вот небольшой пример, использующий часть вашего кода, который вы опубликовали. Я НЕ проверял это на наличие опечаток, и оно не будет компилироваться, но должно помочь дать общее представление о том, о чем я говорю….
namespace Company.Models
{
public class AgencyBean
{
public AgencyName{get;set;}
public AgencyId{get;set;}
// other properties...
}
}
namespace Company.Controllers
{
public class MyController : Controller
{
private readonly IMyService myService;
public MyController(IMyService myService) // <-- this is your dependency injection here...
{
this.myService = myService;
}
[WebMethod]
[ScriptMethod(UseHttpGet = true)]
public static String createGUID(string name)
{
var model = new AgencyBean();
model.AgencyId = 1;
model = myService.getAgency(agencyBean);
return model;
}
}
}
namespace Company.Services
{
public class MyService
{
private readonly IMyRepository myRepository;
public MyService(IMyRepository myRepository) // <-- this is your dependency injection here...
{
this.myRepository = myRepository;
}
public AgencyBean getAgency(AgencyBean model){
var dataTable = myRepository.getAgencyData(model.AgencyId);
// fill other properties of your model you have...
// ...
// ...
return model;
}
}
}
namespace Company.Repositories
{
public class MyRepository : IDatabaseCommon // <-- some interface you would use to ensure that all repo type objects get connection strings or run other necessary database-like setup methods...
{
private readonly String connectionString{get;set;}
public MyRepository()
{
this.connectionString = //get your connection string from web.config or somewhere else...;
}
public DataTable getAgencyData(int id){
var dataTable = new DataTable();
// perform data access and fill up a data table
return dataTable;
}
}
}
Комментарии:
1. Я где-то читал, что моя бизнес-логика должна быть в модели, а контроллер должен быть как можно более простым, поэтому я начал кодировать таким образом .. затем я нашел похожий пост, где люди рекомендовали иметь уровень обслуживания, как вы мне указали. Итак, в вашем примере IMyService — это интерфейс, расположенный в новом файле, который содержит мои запросы, верно? Я просто немного запутался в том, где искать определенные файлы, поскольку я не хочу «ломать» этот шаблон MVC…
2. IMyService — это интерфейс, который вы создаете в другом файле, да. Но это НЕ то место, где вы бы писали свои запросы, а что нет. Если вы хотите написать кучу SQL-команд, я бы порекомендовал другой класс «model», такой как «QueryModel», и это будет набор констант, которые возвращают ваши строки sql. Но на самом деле, я лично этого не делаю. Скорее я использую хранимые процедуры / функции на уровне базы данных и вызываю их из кода приложения. Хранимые в БД процедуры / функции будут содержать весь ваш SQL.
3. Теперь я понимаю вашу точку зрения, я отправляю модель в качестве параметра, заполняю ее в MyService, используя MyRepository с DI, а затем возвращаю модель. Еще один вопрос, я установил Unity DI из Nugget, но получаю ошибку без параметров, должен ли я добавить что-то вручную в свой Application_Start() или это то, что должно быть добавлено установщиком?
4. Обычно для этих DI-фреймворков вам нужно добавить новую ссылку на ваш проект… по крайней мере, я знаю, что вы делаете для Autofac. Я лично никогда не использовал Unity DI, но я уверен, что у них есть какое-то руководство по началу работы. Я считаю, что это «встроенная» платформа di, которую предоставляет Microsoft. Вот хорошее пошаговое руководство по использованию Unity. geekswithblogs.net/danielggarcia/archive/2014/01/23 /…