关于将从数据访问层中的数据库获取的值分配给WCF层的数据协定的正确方法,我有一个问题。
考虑一个简单的场景,从中获取数据库中所有学生的列表,然后将其分配给学生数据合同。
我的学生资料合约如下:
[DataContract]
public class StudentDC
{
[DataMember]
public int StudentID { get; set; }
[DataMember]
public string StudentName { get; set; }
}
在我的数据访问类中,我会有一个像List GetAllStudents()
这样的方法我的问题是我的GetAllStudents()方法的实现。是否可以看起来如下:
公开列表GetAllStudents() {
List<StudentDC> studentDCs = new List<StudentDC>();
var students = db.Students_TB.Select(s => s).ToList();
foreach(Student_TB student in students)
{
StudentDC studentDC = new StudentDC();
studentDC.StudentID = student.StudentID;
studentDC.StudentName = student.StudentName;
studentDCs.Add(studentDC);
}
return studentDCs;
}
上述为数据协定赋值的方法是正确的,还是应该让学生业务对象类接受数据访问层中的数据,然后将值传递给服务契约实现中的数据契约,如下:
我会有以下学生业务对象类:
公共班StudentBO {
int studentID;
string studentName;
public int StudentID
{
get { return studentID; }
set { studentID = value; }
}
public <return type> BusinessLogicMethod1()
{
// Implementation
}
}
在数据访问层中,我会将从数据库获取的值分配给学生业务对象的集合,如下所示:
public List<StudentBO> GetAllStudents()
{
List<StudentBO> studentBOs = new List<StudentBO>();
var students = db.Students_TB.Select(s => s).ToList();
foreach(Student_TB student in students)
{
StudentBO studentBO = new StudentBO();
studentBO.StudentID = student.StudentID;
studentBO.StudentName = student.StudentName;
studentBOs.Add(studentBO);
}
return studentBOs;
}
然后,学生业务对象中的值将被分配给服务合同实施中的学生数据合同,从那里通过网络发送。
上述两种方式中的哪一种是正确的方法?
答案 0 :(得分:2)
首先,您应该询问以下设计目标:
将数据层与业务对象分离的主要思想是在它们之间进行一定程度的抽象。因此,持久层(又称:数据访问层)中的更改不会对更高级别的业务逻辑产生重大影响。业务逻辑也是如此......如果有变化......持久层的变化很小。
另一个方面是代码的可测试性。您可以为业务逻辑提供单元测试用例,并在没有连接到实际DB的持久层的情况下运行它们。相反,您可以在持久层中使用“模拟”类,这样您就可以在内存中运行并测试业务层而无需连接到数据库。
最后,如果您不期望在应用程序的整个生命周期中更改任何一个图层并且维护代码不是预期的,那么您可以使用它。 但在大多数情况下,应用程序都有变化,而维护成本是关键点之一......而层叠松耦合在这里是一个很大的帮助。
您还可以考虑使用AutoMapper
将数据访问层和业务层对象之间的映射外部化答案 1 :(得分:0)
如果我理解正确,问题基本上是以下两个选项更“正确”:
我会说前者。您的业务对象用于封装应用程序业务域的逻辑,您的DTO用于帮助将数据从您的应用程序移动到其客户端。不仅是从数据库对象复制到业务对象,而是从那里向DTO更多努力,有些人说(特别是在Command-Query Responsibility Segregation世界中)业务对象的属性甚至不应该公开访问,因为这暴露了他们的内部状态并违反封装。所以是的 - 在我看来,直接从ORM数据库对象复制到DTO是好的,也是更正确的。
同样@ user1697575指出AutoMapper以帮助您进行映射是完全正确的:)