#asp.net-mvc #ado.net
#asp.net-mvc #ado.net
Вопрос:
Я новичок в C # и MVC. Я прочитал несколько книг и провел время на этом сайте, читая вопросы и ответы по различным темам. У меня запущен тестовый проект для ознакомления с основами, который запрашивает список групп и возвращает их в простое представление. Мне нравится идея шаблона репозитория, и я попробовал ее реализовать. Несколько замечаний… На данный момент я не использую EF или Linq2SQL, но, возможно, в будущем. Я не уверен, сохраню ли я свои инструкции using в GroupRepository или добавлю несколько инструкций Dispose через Try / Catch / Finally, поскольку мне все равно нужен способ управления исключениями.
Просто хотел получить совет / критику по моей текущей настройке, поскольку я продолжаю обучение.
Base.cs
namespace Test.Models
{
public class Base : IDisposable
{
protected string Connection
{
get
{
return System.Configuration.ConfigurationManager.ConnectionStrings["TestDB"].ConnectionString;
}
}
}
}
Group.cs
namespace Test.Models
{
public class Group
{
public int ID { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public DateTime Created { get; set; }
}
}
GroupRepository.cs
namespace Test.Models
{
public class GroupRepository : Base, IGroupRepository
{
public List<Group> GetAllGroups()
{
List<Group> groups = new List<Group>();
SqlDataReader reader;
using (SqlConnection conn = new SqlConnection(Connection))
using (SqlCommand cmd = new SqlCommand("GetAllGroups", conn))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
conn.Open();
reader = cmd.ExecuteReader();
while (reader.Read())
{
Group group = new Group();
group.ID = reader.GetInt32(0);
group.Name = reader.GetString(1);
group.IsActive = reader.GetBoolean(2);
group.Created = reader.GetDateTime(3);
groups.Add(group);
}
}
return groups;
}
}
}
IGroupRepository.cs
namespace Test.Models
{
public interface IGroupRepository
{
List<Group> GetAllGroups();
}
}
GroupController
namespace Test.Controllers
{
public class GroupController : Controller
{
private IGroupRepository _repository;
public GroupController() : this(new GroupRepository())
{
}
public GroupController(IGroupRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
return View(_repository.GetAllGroups());
}
}
}
Вид
@model IEnumerable<Test.Models.Group>
@{
ViewBag.Title = "Group List";
}
<table>
@foreach (var item in Model) {
<tr>
<td>
@item.ID
</td>
<td>
@item.Name
</td>
<td>
@item.IsActive
</td>
<td>
@item.Created
</td>
</tr>
}
</table>
Спасибо всем!
Ответ №1:
Для базовых проектов / изучаем это, если все в порядке. Как только вы начнете разбираться в более сложных сценариях, вы обнаружите, что данные, которые вы отображаете в своих представлениях, будут меньше походить на то, как они хранятся в базе данных, и вам, возможно, захочется иметь модели, специфичные для ваших представлений, а не возвращать модели непосредственно из вашего репозитория в ваши представления.
Однако это то, что вы можете настроить по ходу работы, и если вы просто выполняете базовые операции, то все в порядке.
Еще одна вещь, которая имеет тенденцию быстро становиться избыточной, — это наличие определенных методов доступа к данным в вашем репозитории. Обычно то, что я пытаюсь сделать, это создать объект запроса и передать его в репозиторий, который выполняет запрос, а затем возвращает результаты. Это помогает мне избежать переопределения контракта IRepository каждый раз, когда я хочу получить новый набор данных или запросить другой набор параметров.
Помимо этого, все выглядит довольно стандартно, и основная концепция разделения доступа к данным от контроллеров через репозиторий является надежной.
Вот (очень простой) пример реализации шаблона объекта запроса (на самом деле это просто для того, чтобы дать вам представление, вы захотите очистить его перед началом использования):
public class GroupQueryParams
{
public int? GroupId {get;set;}
public string GroupName {get;set;}
}
public class GroupRepository : Base, IGroupRepository
{
public List<Group> GetGroups(GroupQueryParams query)
{
var storedProcName = "GetAllGroups";
if(query.GroupId.HasValue)
storedProcName = "GetGroupById";
if(!string.IsNullOrEmpty(query.GroupName))
storedProcName = "GetGroupByName";
//setup a parameter collection here to pass into the command
List<Group> groups = new List<Group>();
SqlDataReader reader;
using (SqlConnection conn = new SqlConnection(Connection))
using (SqlCommand cmd = new SqlCommand(storedProcName, conn))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
conn.Open();
reader = cmd.ExecuteReader();
while (reader.Read())
{
Group group = new Group();
group.ID = reader.GetInt32(0);
group.Name = reader.GetString(1);
group.IsActive = reader.GetBoolean(2);
group.Created = reader.GetDateTime(3);
groups.Add(group);
}
}
return groups;
}
}
Таким образом, у вас есть единственный метод «GetGroups», и вы можете изменять параметры запроса и базовую логику столько, сколько захотите, но вам не нужно переопределять интерфейс каждый раз, когда вы хотите добавить новый запрос.
Комментарии:
1. спасибо за полезный отзыв, lomaxx, если у вас есть свободная минутка, было бы полезно посмотреть пример «создания объекта запроса и передачи его в репозиторий»