我正在创建一个项目,其中将使用ADO.NET作为数据访问层与数据库进行交互。
现在我很困惑的是:
1)此应用程序中应该包含域对象吗?
2)我的sql查询结果是否应始终与域对象绑定?
3)如果我不使用域对象,那么我是否应该总是从数据访问层返回自定义模型,这些模型具有要在Web api服务中返回的所有内容?
4)如果我使用域模型,并且在某些情况下我想显示多个表中的数据或类似情况,例如:
public class Employee
{
int id;
List<Skills>();
}
我可以在EF中轻松完成此操作,但是使用ado.net和域对象将具有如下所示的结构:
public class Employee
{
int id;
}
public class Skill
{
int id;
int EmployeeId;
}
当然,我可以先获取员工列表,然后为每个员工获取基于员工ID的技能列表,但这不是一件容易的事 我将不得不对每个员工进行查询,以获取其相应的技能,这在基于导航属性的EF中非常简单,并且避免了类似以下的开销:
var employees = //get listof employee in this case domain model
List<Employee>
var employeeModel = new List<EmployeeModel>();
foreach(var employee in employees)
{
EmployeeModel model = new EmployeeModel();
model.id = employee.id;
var skills = GetSkill(employee.id);//Get list of skills in this case
domain model List<Skill>;
employeeModel.Skills = new List<SkillModel>();
foreach(var skill in skills)
{
SkillModel sm = new SkillModel();
sm.Id = skill.Id;
employeeModel.Skills.Add(smm);
}
employeeModel.Add(model);
}
最后,此EmployeeModel将作为响应在我的Web Api服务中返回,因此,此EmployeeModel将仅保存我将在WebApi端点中返回的那些属性。
使用ado.net作为数据访问层时应考虑的架构是什么,如果有人可以帮助我解决以上4个问题,我将不胜感激。
注意::我不想使用ORM(实体框架或Dapper等)。
答案 0 :(得分:5)
1)此应用程序中应该包含域对象吗?
只有您可以对此回答;正确的答案很大程度上取决于您对数据库查询结果的处理方式。如果您的C#代码中有一些特定于字段的逻辑,则可以使用DTO(POCO实体类)。但是有时您可能只想执行一些查询并以JSON形式返回结果,在这种情况下,DTO可能会显得过大。
2)我的sql查询结果是否应始终与域对象绑定?
不,这取决于您。您可以直接使用DbDataReader
处理查询结果,或将其加载到DataTable
(或数据访问库可以提供的类似的更轻量级结构)中。
3)如果我不使用域对象,那么我是否应该始终从数据访问层返回自定义模型,这些自定义模型具有我要在Web api服务中返回的所有内容?
如果您不使用POCO模型,则可以在代码中编写JSON并将其作为ActionResult返回。
4)如果我使用域模型,并且在某些情况下我想显示多个表中的数据
如果您在这里不使用像EF这样的ORM 2可能的情况:
List<Employee>
和List<Skills>
)。然后,如果您需要访问具体“父”实体的子代,请使用LINQ进行其他过滤。如果您不想使用EF或Dapper,还可以检查my library,该可以用于POCO模型或与DataTable这样的通用结构(除了它提供RecordSet结构)。 / p>
答案 1 :(得分:2)
实体框架和延迟加载引用对象是一种合理的方法。要扩展模型,请考虑以下内容。
创建一个链接Employee和Skills表的SQL Server视图,并将其添加到EF模型。该视图可以根据需要设置为最小或最大(例如,仅在对象ID的范围内为最小,或在所有字段中的范围为最大)。
从此视图中,选择具有特定技能ID的所有记录,现在您拥有所需的员工。由于视图是在SQL Server中编译的,因此将尽快完成。
您还可以在代码中加入Employee和Skill对象,只返回雇员。在LINQ中,您可以查看为代码生成的SQL
答案 2 :(得分:2)
在应用程序中创建域模型是一种很好的方法。您只需要将数据绑定到模型。根据数据库表创建模型。如果任何表具有对其他表的引用,也将其引用包括在模型中,则将使您轻松将数据映射到模型。 我建议您使用微型ORM,它将帮助您将数据映射到模型,否则您将需要映射自己。
答案 3 :(得分:2)
我将尝试给出更具体的答案,这些应该为您提供实用的指导原则。
1)此应用程序中应该包含域对象吗?
这取决于。对于非常简单的应用程序,则不需要它。对于更复杂的应用程序,绝对推荐。
2)我的sql查询结果是否应始终与域对象绑定?
是的,如果您要使用域模型。如果您没有域模型或试图返回一个简单值(例如整数),则不会。
3)如果我不使用域对象,那么我是否应该始终从数据访问层返回自定义模型,这些自定义模型具有我要在Web api服务中返回的所有内容?
如果您没有域模型,那么您的DAL将成为Web api服务的直接服务方。因此,无论Web API需要什么,都需要从DAL获取。您可以一次性返回所有内容(一个方法调用),也可以通过多次方法调用使api调用DAL。显然,一次性检索所有内容会更好,但是更适合服务层。 DAL应该一次返回聚合。但是,如果没有域模型和更高级的方法,这可能是太多思考了。
4)如果我使用域模型,并且在某些情况下想要显示多个表或类似情况的数据
我将使用join运行一个SQL查询。然后,我将遍历行并从行创建父对象和子对象,然后以这种方式返回对象。实际上,这就是Entity Framework对导航属性所做的工作-它渴望使用join加载整个结构。如果您要最大程度地优化它,它不会执行多个查询,也不应执行任何查询。
如果您对我提到的任何内容有疑问,请告诉我。
答案 4 :(得分:1)
我同意Tengiz的回答。但是,可以使用Active Record pattern,如果按域对象表示要使用域驱动的设计方法,则DAL应该抽象内部的数据访问逻辑,最好对每个域使用Repository pattern聚合对象。另外,您可以分开模型进行读写,然后可以使用CQRS模式。
无论如何,您都需要在数据访问对象中运行sql命令/存储过程,然后从ADO.NET数据读取器,数据集,数据表中填充域对象,并将它们公开给域模型。
请注意,DTO的名称与您的内部域通信,这是将域对象与DTO(数据合同)分开的一种好习惯。
答案 5 :(得分:0)
我只是想为您提供方案4的另一种选择。
4)如果我使用域模型,并且在某些情况下我想显示>多个表或类似情况的数据
看看我在以下问题中提供的答案: Loading related objects in memory (without an ORM)
我正在使用匿名类型和LINQ在多个表之间映射查询数据。