三层架构:获取所有数据和验证
Three-Tier Architecture: Get All Data and Validations
我正在做的项目是'University Management System',这是一个很大的项目。现在,我正在实施运行良好的学生注册部分(该项目的一小部分)。我在 ASP.NET MVC 模板中使用了 'Three-Tier Architecture' 和 'ORM - EF' 。在项目中,我需要根据学生的年级、部门等对注册学生进行一些验证。所以有 DAL、BLL、最后是控制器和视图等部分。我已经在控制器中完成验证并从 BLL 获取数据,BLL 再次从 DAL 检索数据(这是 'Three-Tier Architecture' 的简单条件)。所以我的问题是:
1) 可以在控制器中进行验证吗?
2) 如果不需要并且需要在 BLL 中进行,是否会很好,为什么或者我可以
继续在控制器中做?
注意:对我来说,在控制器或 BLL 中进行验证似乎没问题,而且是一样的。有没有效果?
现在,我做了以下事情:
DAL:
public List<Student> Add(int studentID, string studentName, string email, DateTime regDate)
{
List<Student> lst = null;
Student aStudent = new Student();
aStudent.StudentID = studentID;
aStudent.StudentName = studentName;
aStudent.Email = email;
aStudent.RegDate = regDate;
try
{
db.Students.Add(aStudent);
db.SaveChanges();
}
catch (Exception ex)
{
ex.ToString();
}
return lst;
}
BLL:
public List<Student> Add(int studentID, string studentName, string email, DateTime regDate)
{
return aStudentGateway.Add(studentID, studentName, email, regDate);
}
控制器:
/**Student Registration - Starts**/
[HttpPost]
public ActionResult AddStudent(Student aStudent)
{
List<Department> departments = aDepartmentManager.GetAllDepartments();
List<DepartmentViewModel> departmentsViewModel = aDepartmentManager.GetAllDepartmentViewModel();
DateTime yearInDateTime = Convert.ToDateTime(Request.Form["RegDate"]);
string extractYear = yearInDateTime.ToString();
var year = DateTime.Parse(extractYear).Year;
int department = Convert.ToInt32(Request.Form["Department"]);
List<Student> studentList = aStudentManager.GetAllStudents();
int count = 1;
var query = (from c in studentList
where c.Department == department && c.Year == year
select c).ToList();
foreach (var c in query)
{
if (query.Count() > 0)
{
int m = Convert.ToInt32(c.StudentID);
count = m + 1; //Incrementing the numbers by one with the table column
}
else
{
int m = 1;
count = m + 1; //Incrementing the numbers by one with the variable assigned one
}
}
Student student = new Student();
student.StudentName = Request.Form["StudentName"];
student.Email = Request.Form["Email"];
student.RegDate = Convert.ToDateTime(Request.Form["RegDate"]);
student.StudentID = count;
if (aStudentManager.ExistEmailAny(student.Email))
{
ViewBag.ErrorMessage = "Email already exists";
}
else
{
aStudentManager.Add(aStudent.StudentID, aStudent.StudentName, aStudent.Email, aStudent.RegDate);
ViewBag.Message = "Registration successful. See below to verify.";
/**This section used to show student details after registration**/
var result = (from c in departments
join d in departmentsViewModel on c.DepartmentID equals d.DepartmentId
where d.DepartmentId == department
select c);
foreach (var items in result)
{
if (count.ToString().Length > 1)
{
ViewBag.StudentID = items.Code + "-" + year + "-" + "0" + count;
}
else
{
ViewBag.StudentID = items.Code + "-" + year + "-" + "00" + count;
}
StudentViewModel.StudentID = student.StudentID;
StudentViewModel.StudentName = student.StudentName;
StudentViewModel.Email = student.Email;
StudentViewModel.RegDate = student.RegDate;
}
/**This section used to show student details after registration**/
}
return View();
}
/**Student Registration - Ends**/
1) Is it OK to do the validations in the controller?
完全没有,最好使用 Data Annotation Validator Attributes
,并在您的模型中进行验证 class。
第二件事,你正在控制器中做一些 DAL 的事情,比如
List<Department> departments = aDepartmentManager.GetAllDepartments();
List<DepartmentViewModel> departmentsViewModel = aDepartmentManager.GetAllDepartmentViewModel();
var query = (from c in studentList
where c.Department == department && c.Year == year
select c).ToList();
这些所有查询都应该在 DAL 中,这正是使用 DAL 与数据库交互,并保持您的控制器干净。
第三件事,
如果将Student
传给控制器,则不需要使用Request.Form
获取每个属性。
希望这是有道理的!
我会在不同的层中提供多个验证步骤,具体取决于层的上下文和含义。
首先,最佳做法是同时在客户端和服务器端提供验证。
对于客户端,您应该为必填字段和其他简单验证提供字段检查。如果您使用的是 MVC you can use data annotations.
应在控制器中复制相同的验证。在这里,您应该快速失败,将某种合同应用于已传递的参数。一种好的做法是使用 Code Contracts 提供需要满足的先决条件才能在您的执行管道中继续进行。
在业务层提供业务逻辑中需要做的校验。
最后,在数据访问层中提供持久化数据所需的所有检查。如果您使用的是 EF,一个好的做法是在 Scott Gu 的博客中实现 IValidatableObject for your entity classes. Here,您可以找到解释此技术的 post。
尽管这种方法看起来会引入重复,但它会提供数据的一致性并分离层之间的关注点。
我正在做的项目是'University Management System',这是一个很大的项目。现在,我正在实施运行良好的学生注册部分(该项目的一小部分)。我在 ASP.NET MVC 模板中使用了 'Three-Tier Architecture' 和 'ORM - EF' 。在项目中,我需要根据学生的年级、部门等对注册学生进行一些验证。所以有 DAL、BLL、最后是控制器和视图等部分。我已经在控制器中完成验证并从 BLL 获取数据,BLL 再次从 DAL 检索数据(这是 'Three-Tier Architecture' 的简单条件)。所以我的问题是:
1) 可以在控制器中进行验证吗?
2) 如果不需要并且需要在 BLL 中进行,是否会很好,为什么或者我可以 继续在控制器中做?
注意:对我来说,在控制器或 BLL 中进行验证似乎没问题,而且是一样的。有没有效果?
现在,我做了以下事情:
DAL:
public List<Student> Add(int studentID, string studentName, string email, DateTime regDate)
{
List<Student> lst = null;
Student aStudent = new Student();
aStudent.StudentID = studentID;
aStudent.StudentName = studentName;
aStudent.Email = email;
aStudent.RegDate = regDate;
try
{
db.Students.Add(aStudent);
db.SaveChanges();
}
catch (Exception ex)
{
ex.ToString();
}
return lst;
}
BLL:
public List<Student> Add(int studentID, string studentName, string email, DateTime regDate)
{
return aStudentGateway.Add(studentID, studentName, email, regDate);
}
控制器:
/**Student Registration - Starts**/
[HttpPost]
public ActionResult AddStudent(Student aStudent)
{
List<Department> departments = aDepartmentManager.GetAllDepartments();
List<DepartmentViewModel> departmentsViewModel = aDepartmentManager.GetAllDepartmentViewModel();
DateTime yearInDateTime = Convert.ToDateTime(Request.Form["RegDate"]);
string extractYear = yearInDateTime.ToString();
var year = DateTime.Parse(extractYear).Year;
int department = Convert.ToInt32(Request.Form["Department"]);
List<Student> studentList = aStudentManager.GetAllStudents();
int count = 1;
var query = (from c in studentList
where c.Department == department && c.Year == year
select c).ToList();
foreach (var c in query)
{
if (query.Count() > 0)
{
int m = Convert.ToInt32(c.StudentID);
count = m + 1; //Incrementing the numbers by one with the table column
}
else
{
int m = 1;
count = m + 1; //Incrementing the numbers by one with the variable assigned one
}
}
Student student = new Student();
student.StudentName = Request.Form["StudentName"];
student.Email = Request.Form["Email"];
student.RegDate = Convert.ToDateTime(Request.Form["RegDate"]);
student.StudentID = count;
if (aStudentManager.ExistEmailAny(student.Email))
{
ViewBag.ErrorMessage = "Email already exists";
}
else
{
aStudentManager.Add(aStudent.StudentID, aStudent.StudentName, aStudent.Email, aStudent.RegDate);
ViewBag.Message = "Registration successful. See below to verify.";
/**This section used to show student details after registration**/
var result = (from c in departments
join d in departmentsViewModel on c.DepartmentID equals d.DepartmentId
where d.DepartmentId == department
select c);
foreach (var items in result)
{
if (count.ToString().Length > 1)
{
ViewBag.StudentID = items.Code + "-" + year + "-" + "0" + count;
}
else
{
ViewBag.StudentID = items.Code + "-" + year + "-" + "00" + count;
}
StudentViewModel.StudentID = student.StudentID;
StudentViewModel.StudentName = student.StudentName;
StudentViewModel.Email = student.Email;
StudentViewModel.RegDate = student.RegDate;
}
/**This section used to show student details after registration**/
}
return View();
}
/**Student Registration - Ends**/
1) Is it OK to do the validations in the controller?
完全没有,最好使用 Data Annotation Validator Attributes
,并在您的模型中进行验证 class。
第二件事,你正在控制器中做一些 DAL 的事情,比如
List<Department> departments = aDepartmentManager.GetAllDepartments();
List<DepartmentViewModel> departmentsViewModel = aDepartmentManager.GetAllDepartmentViewModel();
var query = (from c in studentList
where c.Department == department && c.Year == year
select c).ToList();
这些所有查询都应该在 DAL 中,这正是使用 DAL 与数据库交互,并保持您的控制器干净。
第三件事,
如果将Student
传给控制器,则不需要使用Request.Form
获取每个属性。
希望这是有道理的!
我会在不同的层中提供多个验证步骤,具体取决于层的上下文和含义。
首先,最佳做法是同时在客户端和服务器端提供验证。
对于客户端,您应该为必填字段和其他简单验证提供字段检查。如果您使用的是 MVC you can use data annotations.
应在控制器中复制相同的验证。在这里,您应该快速失败,将某种合同应用于已传递的参数。一种好的做法是使用 Code Contracts 提供需要满足的先决条件才能在您的执行管道中继续进行。
在业务层提供业务逻辑中需要做的校验。
最后,在数据访问层中提供持久化数据所需的所有检查。如果您使用的是 EF,一个好的做法是在 Scott Gu 的博客中实现 IValidatableObject for your entity classes. Here,您可以找到解释此技术的 post。
尽管这种方法看起来会引入重复,但它会提供数据的一致性并分离层之间的关注点。