ASP.Net: 寻找设计视图模型和模型代码的正确方法
ASP.Net: Looking for right approach to design view model and model code
我是 ASP.Net MVC 的新手。在我的项目中,我没有使用 Entity Framework,而是使用 ADO.net。这是我的视图模型设计的代码。请看
动作
public class WebGrid_Sample1Controller : Controller
{
// GET: WebGrid
public ActionResult Show1(StudentVm oSVm)
{
StudentVm SVm = new StudentVm(); //.GetStudents(oSVm);
SVm.Students= SVm.GetStudents(oSVm);
return View(SVm);
}
}
我的模型和视图模型代码
public class StudentVm
{
public int page { get; set; }
public int RowCount { get; set; }
public int PageSize { get; set; }
public int CurrentPage { get; set; }
public string sort { get; set; }
public string sortdir { get; set; }
public IList<Student> Students { get; set; }
public StudentVm()
{
PageSize = 5;
sort = "ID";
sortdir = "ASC";
CurrentPage = 1;
}
public IList<Student> GetStudents(StudentVm oSVm)
{
int StartIndex = 0, EndIndex = 0;
if (oSVm.page == 0)
oSVm.page = 1;
StartIndex = ((oSVm.page * oSVm.PageSize) - oSVm.PageSize) + 1;
EndIndex = (oSVm.page * oSVm.PageSize);
CurrentPage = StartIndex;
if (string.IsNullOrEmpty(oSVm.sort))
oSVm.sort = "ID";
if (string.IsNullOrEmpty(oSVm.sortdir))
oSVm.sortdir = "ASC";
string connectionStringName = System.Configuration.ConfigurationManager.ConnectionStrings["StudentDBContext"].ConnectionString;
IList<Student> _Student = new List<Student>();
string strSQL = "SELECT ID, FirstName,LastName,IsActive,StateName,CityName FROM vwListStudents WHERE ID >=" + StartIndex + " AND ID <=" + EndIndex;
strSQL += " ORDER BY " + oSVm.sort + " " + oSVm.sortdir;
strSQL += ";SELECT COUNT(*) AS Count FROM vwListStudents";
using (SqlConnection connection = new SqlConnection(connectionStringName))
{
SqlCommand command = new SqlCommand(
strSQL, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
_Student.Add(new Student()
{
ID = Convert.ToInt32(reader["ID"].ToString()),
FirstName = reader["FirstName"].ToString(),
LastName = reader["LastName"].ToString(),
IsActive = Convert.ToBoolean(reader["IsActive"]),
StateName = reader["StateName"].ToString(),
CityName = reader["CityName"].ToString()
});
}
}
reader.NextResult();
if (reader.HasRows)
{
while (reader.Read())
{
RowCount = Convert.ToInt32(reader["Count"].ToString());
}
}
reader.Close();
}
//RowCount = _Student.Count;
return _Student;
}
}
型号
public class Student
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool IsActive { get; set; }
public string StateName { get; set; }
public string CityName { get; set; }
}
有人查看我的视图模型代码并说 视图模型不应包含实现。 View Models
是在客户端、控制器和视图之间传递数据的容器。
他给出了vm code
的新局部设计
public class StudentVm
{
public int page { get; set; }
public int RowCount { get; set; }
public int PageSize { get; set; }
public int CurrentPage { get; set; }
public string sort { get; set; }
public string sortdir { get; set; }
public IList<Student> Students { get; set; }
}
public class Student
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool IsActive { get; set; }
public string StateName { get; set; }
public string CityName { get; set; }
}
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Show1(StudentVm oSVm)
{
return View(oSVm);
}
所以我的问题是将数据库交互例程放在哪里?
我说的是这一行
public IList<Student> GetStudents(StudentVm oSVm)
{
int StartIndex = 0, EndIndex = 0;
if (oSVm.page == 0)
oSVm.page = 1;
StartIndex = ((oSVm.page * oSVm.PageSize) - oSVm.PageSize) + 1;
EndIndex = (oSVm.page * oSVm.PageSize);
CurrentPage = StartIndex;
if (string.IsNullOrEmpty(oSVm.sort))
oSVm.sort = "ID";
if (string.IsNullOrEmpty(oSVm.sortdir))
oSVm.sortdir = "ASC";
string connectionStringName = System.Configuration.ConfigurationManager.ConnectionStrings["StudentDBContext"].ConnectionString;
IList<Student> _Student = new List<Student>();
string strSQL = "SELECT ID, FirstName,LastName,IsActive,StateName,CityName FROM vwListStudents WHERE ID >=" + StartIndex + " AND ID <=" + EndIndex;
strSQL += " ORDER BY " + oSVm.sort + " " + oSVm.sortdir;
strSQL += ";SELECT COUNT(*) AS Count FROM vwListStudents";
using (SqlConnection connection = new SqlConnection(connectionStringName))
{
SqlCommand command = new SqlCommand(
strSQL, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
_Student.Add(new Student()
{
ID = Convert.ToInt32(reader["ID"].ToString()),
FirstName = reader["FirstName"].ToString(),
LastName = reader["LastName"].ToString(),
IsActive = Convert.ToBoolean(reader["IsActive"]),
StateName = reader["StateName"].ToString(),
CityName = reader["CityName"].ToString()
});
}
}
reader.NextResult();
if (reader.HasRows)
{
while (reader.Read())
{
RowCount = Convert.ToInt32(reader["Count"].ToString());
}
}
reader.Close();
}
//RowCount = _Student.Count;
return _Student;
}
所以我的要求是任何人都可以使用数据库交互例程重构我的代码。
如何设计整个代码,包括 viewmodel、model 和 db interaction 例程。我正在使用 ADO.Net。到目前为止,无论我阅读什么示例文章来重构我的代码,所有项目示例都使用 EF。所以请有人用数据库交互例程重组我的代码。提前致谢。
不要在视图模型中混合使用数据访问代码。这违背了关注点分离的全部目的。引入视图模型的整个想法是不要将 ORM 端实体混合到视图层。
您的视图模型应该是 lean-flat POCO/DTO 类。这些 DTO 用于在一层与另一层之间传输数据。它应该不知道从哪里获取数据。
您应该有另一个 layer/class,它将为您提供数据,并且您会将实体映射到您的视图模型。如果您不喜欢手动映射,可以使用像 Automapper 这样的映射库来实现。
您可以根据应用的复杂程度以多种不同的方式设计您的 application/layers。一个快速简单的实现就像
YourProject.Common :该项目将 DTO's/POCO 存储在您的项目中。如果需要,您可以根据需要将视图模型保留在这里。
YourProject.Data :此项目引用了您的通用项目和 returns 数据,格式为那些 DTO 类。
YourProject.Web/UI:您的 Web/API 项目。这将引用 Data 项目和 Commin 项目并调用数据访问方法来获取数据。您可以在此处执行 属性 映射(从实体读取并设置为查看模型)。
您可以向堆栈添加更多层,例如 UI 和数据访问之间的 Business/Service 层 以执行一些业务逻辑/映射等..
明智地使用分层,如果你盲目地试图创建很多实际上不需要的层,你最终会弄得一团糟。
您需要做的第一件事是将 db-access 代码移出您的视图模型并移入存储库 class。请参阅下面的示例:
public class WebGridSampleController
{
private StudentRepository _data;
public WebGridSampleController()
{
_data = new StudentRepository();
}
public ActionResult Show1(StudentVm oSVm)
{
var students = _data.GetStudents(oSVm.page, oSVm.pageSize, oSVm.sort, oSVm.sortDir);
oSVm.Students = students.ToList();
return View(oSVm);
}
}
public class StudentRepository
{
public IEnumerable<Student> GetStudents(int page, int pageSize, string sort, string sortDir)
{
// Put the code that you have in StudentVM.GetAllStudents here
}
}
您发布的代码还有其他问题。我认为其中大部分归结为 classes 和变量的命名不当。例如:这里的景色是什么?它不是查看特定学生的详细信息,是吗?
因此,StudentVm(或 StudentViewModel)可能应该命名为 StudentListViewModel.另外,Controller 应该命名为 StudentController,因为它控制着学生的观看。此外,在我看来,动作 Show1 应该被称为 List。
考虑到这些,示例可以更新如下:
public class StudentController
{
private StudentRepository _data;
public StudentController()
{
_data = new StudentRepository();
}
public ActionResult List(StudentListViewModel viewModel)
{
var students = _data.GetStudents(viewModel.Page, viewModel.PageSize, viewModel.Sort, viewModel.SortDirection);
viewModel.Students = students.ToList();
return View(viewModel);
}
}
public class StudentRepository
{
public IEnumerable<Student> GetStudents(int page, int pageSize, string sort, string sortDir)
{
// Put the code that you have in StudentVM.GetAllStudents here
}
}
我们也可以解决依赖注入的话题,但目前似乎有点过头了。另外,此时我不会为每个 "layer" 创建一个项目。只需确保您的模型和视图模型不引用任何数据访问内容。
我是 ASP.Net MVC 的新手。在我的项目中,我没有使用 Entity Framework,而是使用 ADO.net。这是我的视图模型设计的代码。请看
动作
public class WebGrid_Sample1Controller : Controller
{
// GET: WebGrid
public ActionResult Show1(StudentVm oSVm)
{
StudentVm SVm = new StudentVm(); //.GetStudents(oSVm);
SVm.Students= SVm.GetStudents(oSVm);
return View(SVm);
}
}
我的模型和视图模型代码
public class StudentVm
{
public int page { get; set; }
public int RowCount { get; set; }
public int PageSize { get; set; }
public int CurrentPage { get; set; }
public string sort { get; set; }
public string sortdir { get; set; }
public IList<Student> Students { get; set; }
public StudentVm()
{
PageSize = 5;
sort = "ID";
sortdir = "ASC";
CurrentPage = 1;
}
public IList<Student> GetStudents(StudentVm oSVm)
{
int StartIndex = 0, EndIndex = 0;
if (oSVm.page == 0)
oSVm.page = 1;
StartIndex = ((oSVm.page * oSVm.PageSize) - oSVm.PageSize) + 1;
EndIndex = (oSVm.page * oSVm.PageSize);
CurrentPage = StartIndex;
if (string.IsNullOrEmpty(oSVm.sort))
oSVm.sort = "ID";
if (string.IsNullOrEmpty(oSVm.sortdir))
oSVm.sortdir = "ASC";
string connectionStringName = System.Configuration.ConfigurationManager.ConnectionStrings["StudentDBContext"].ConnectionString;
IList<Student> _Student = new List<Student>();
string strSQL = "SELECT ID, FirstName,LastName,IsActive,StateName,CityName FROM vwListStudents WHERE ID >=" + StartIndex + " AND ID <=" + EndIndex;
strSQL += " ORDER BY " + oSVm.sort + " " + oSVm.sortdir;
strSQL += ";SELECT COUNT(*) AS Count FROM vwListStudents";
using (SqlConnection connection = new SqlConnection(connectionStringName))
{
SqlCommand command = new SqlCommand(
strSQL, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
_Student.Add(new Student()
{
ID = Convert.ToInt32(reader["ID"].ToString()),
FirstName = reader["FirstName"].ToString(),
LastName = reader["LastName"].ToString(),
IsActive = Convert.ToBoolean(reader["IsActive"]),
StateName = reader["StateName"].ToString(),
CityName = reader["CityName"].ToString()
});
}
}
reader.NextResult();
if (reader.HasRows)
{
while (reader.Read())
{
RowCount = Convert.ToInt32(reader["Count"].ToString());
}
}
reader.Close();
}
//RowCount = _Student.Count;
return _Student;
}
}
型号
public class Student
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool IsActive { get; set; }
public string StateName { get; set; }
public string CityName { get; set; }
}
有人查看我的视图模型代码并说 视图模型不应包含实现。 View Models
是在客户端、控制器和视图之间传递数据的容器。
他给出了vm code
public class StudentVm
{
public int page { get; set; }
public int RowCount { get; set; }
public int PageSize { get; set; }
public int CurrentPage { get; set; }
public string sort { get; set; }
public string sortdir { get; set; }
public IList<Student> Students { get; set; }
}
public class Student
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool IsActive { get; set; }
public string StateName { get; set; }
public string CityName { get; set; }
}
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Show1(StudentVm oSVm)
{
return View(oSVm);
}
所以我的问题是将数据库交互例程放在哪里?
我说的是这一行
public IList<Student> GetStudents(StudentVm oSVm)
{
int StartIndex = 0, EndIndex = 0;
if (oSVm.page == 0)
oSVm.page = 1;
StartIndex = ((oSVm.page * oSVm.PageSize) - oSVm.PageSize) + 1;
EndIndex = (oSVm.page * oSVm.PageSize);
CurrentPage = StartIndex;
if (string.IsNullOrEmpty(oSVm.sort))
oSVm.sort = "ID";
if (string.IsNullOrEmpty(oSVm.sortdir))
oSVm.sortdir = "ASC";
string connectionStringName = System.Configuration.ConfigurationManager.ConnectionStrings["StudentDBContext"].ConnectionString;
IList<Student> _Student = new List<Student>();
string strSQL = "SELECT ID, FirstName,LastName,IsActive,StateName,CityName FROM vwListStudents WHERE ID >=" + StartIndex + " AND ID <=" + EndIndex;
strSQL += " ORDER BY " + oSVm.sort + " " + oSVm.sortdir;
strSQL += ";SELECT COUNT(*) AS Count FROM vwListStudents";
using (SqlConnection connection = new SqlConnection(connectionStringName))
{
SqlCommand command = new SqlCommand(
strSQL, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
_Student.Add(new Student()
{
ID = Convert.ToInt32(reader["ID"].ToString()),
FirstName = reader["FirstName"].ToString(),
LastName = reader["LastName"].ToString(),
IsActive = Convert.ToBoolean(reader["IsActive"]),
StateName = reader["StateName"].ToString(),
CityName = reader["CityName"].ToString()
});
}
}
reader.NextResult();
if (reader.HasRows)
{
while (reader.Read())
{
RowCount = Convert.ToInt32(reader["Count"].ToString());
}
}
reader.Close();
}
//RowCount = _Student.Count;
return _Student;
}
所以我的要求是任何人都可以使用数据库交互例程重构我的代码。 如何设计整个代码,包括 viewmodel、model 和 db interaction 例程。我正在使用 ADO.Net。到目前为止,无论我阅读什么示例文章来重构我的代码,所有项目示例都使用 EF。所以请有人用数据库交互例程重组我的代码。提前致谢。
不要在视图模型中混合使用数据访问代码。这违背了关注点分离的全部目的。引入视图模型的整个想法是不要将 ORM 端实体混合到视图层。
您的视图模型应该是 lean-flat POCO/DTO 类。这些 DTO 用于在一层与另一层之间传输数据。它应该不知道从哪里获取数据。
您应该有另一个 layer/class,它将为您提供数据,并且您会将实体映射到您的视图模型。如果您不喜欢手动映射,可以使用像 Automapper 这样的映射库来实现。
您可以根据应用的复杂程度以多种不同的方式设计您的 application/layers。一个快速简单的实现就像
YourProject.Common :该项目将 DTO's/POCO 存储在您的项目中。如果需要,您可以根据需要将视图模型保留在这里。
YourProject.Data :此项目引用了您的通用项目和 returns 数据,格式为那些 DTO 类。
YourProject.Web/UI:您的 Web/API 项目。这将引用 Data 项目和 Commin 项目并调用数据访问方法来获取数据。您可以在此处执行 属性 映射(从实体读取并设置为查看模型)。
您可以向堆栈添加更多层,例如 UI 和数据访问之间的 Business/Service 层 以执行一些业务逻辑/映射等..
明智地使用分层,如果你盲目地试图创建很多实际上不需要的层,你最终会弄得一团糟。
您需要做的第一件事是将 db-access 代码移出您的视图模型并移入存储库 class。请参阅下面的示例:
public class WebGridSampleController
{
private StudentRepository _data;
public WebGridSampleController()
{
_data = new StudentRepository();
}
public ActionResult Show1(StudentVm oSVm)
{
var students = _data.GetStudents(oSVm.page, oSVm.pageSize, oSVm.sort, oSVm.sortDir);
oSVm.Students = students.ToList();
return View(oSVm);
}
}
public class StudentRepository
{
public IEnumerable<Student> GetStudents(int page, int pageSize, string sort, string sortDir)
{
// Put the code that you have in StudentVM.GetAllStudents here
}
}
您发布的代码还有其他问题。我认为其中大部分归结为 classes 和变量的命名不当。例如:这里的景色是什么?它不是查看特定学生的详细信息,是吗?
因此,StudentVm(或 StudentViewModel)可能应该命名为 StudentListViewModel.另外,Controller 应该命名为 StudentController,因为它控制着学生的观看。此外,在我看来,动作 Show1 应该被称为 List。
考虑到这些,示例可以更新如下:
public class StudentController
{
private StudentRepository _data;
public StudentController()
{
_data = new StudentRepository();
}
public ActionResult List(StudentListViewModel viewModel)
{
var students = _data.GetStudents(viewModel.Page, viewModel.PageSize, viewModel.Sort, viewModel.SortDirection);
viewModel.Students = students.ToList();
return View(viewModel);
}
}
public class StudentRepository
{
public IEnumerable<Student> GetStudents(int page, int pageSize, string sort, string sortDir)
{
// Put the code that you have in StudentVM.GetAllStudents here
}
}
我们也可以解决依赖注入的话题,但目前似乎有点过头了。另外,此时我不会为每个 "layer" 创建一个项目。只需确保您的模型和视图模型不引用任何数据访问内容。