How does my C# MVC project setup look?
I am new to C# and MVC. I have read a few books and spent time on this site reading Q&A on various topics. I have a test project up and running to get the basics down that queries out a list of Groups and returns them to a simple View. I like the idea of the Repository pattern and have taken a stab at implementing that. A few notes... For now, I am not using EF or Linq2Sql but maybe in the future. I am not sure if I will keep my using statements in the GroupRepository or add some Dispose statements via a Try/Catch/Finally as I need a way to manage exceptions anyway.
Just wanted some advice/critique on my current setup as I continue learning.
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;
}
}
}
开发者_如何学CIGroupRepository.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());
}
}
}
View
@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>
Thanks All!
For basic projects / learning this if fine. Once you start getting into more advanced scenarios you'll find that the data you display in your views will look less like how it's stored in the database and you may want to have models which are specific to your views rather than returning the models directly from your repository into your views.
This is something you can tweak as you go however and if you're just doing basic operations then that's fine.
Another thing that tends to grow redundant quickly is having specific data access methods on your repository. Generally what I try and do is construct a query object and pass that into the repository, which executes the query and then returns the results. This tends to help me avoid redefining the IRepository contract every time I want to get a new set of data, or query by a different set of parameters.
Apart from that everything looks pretty standard and the main concept of separating data access from the controllers via the repository is solid.
Here's a (very basic) sample implementation of a query object pattern (this is really just to give you an idea, you will want to clean it up before you start using it):
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;
}
}
This way you've got a single method "GetGroups" and you can change the query params and the underlying logic as much as you want but don't have to keep redefining the interface every time you want to add a new query.
精彩评论