数据访问层是否可以在Ado.net的情况下返回域对象?

时间:2018-12-12 11:28:43

标签: c# asp.net-web-api ado.net repository-pattern

我正在创建一个项目,其中将使用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等)。

6 个答案:

答案 0 :(得分:5)

  

1)此应用程序中应该包含域对象吗?

只有您可以对此回答;正确的答案很大程度上取决于您对数据库查询结果的处理方式。如果您的C#代码中有一些特定于字段的逻辑,则可以使用DTO(POCO实体类)。但是有时您可能只想执行一些查询并以JSON形式返回结果,在这种情况下,DTO可能会显得过大。

  

2)我的sql查询结果是否应始终与域对象绑定?

不,这取决于您。您可以直接使用DbDataReader处理查询结果,或将其加载到DataTable(或数据访问库可以提供的类似的更轻量级结构)中。

  

3)如果我不使用域对象,那么我是否应该始终从数据访问层返回自定义模型,这些自定义模型具有我要在Web api服务中返回的所有内容?

如果您不使用POCO模型,则可以在代码中编写JSON并将其作为ActionResult返回。

  

4)如果我使用域模型,并且在某些情况下我想显示多个表中的数据

如果您在这里不使用像EF这样的ORM 2可能的情况:

  • 如果这是2个(或更多)联接表的结果:为此,您可以为此查询结果完全添加特殊的POCO模型,或使用通用数据容器(如DataTable)来处理结果
  • 如果这是父子(1-n):执行2个查询并将结果作为2个POCO模型集合(例如,这些雇员的List<Employee>List<Skills>)。然后,如果您需要访问具体“父”实体的子代,请使用LINQ进行其他过滤。

如果您不想使用EF或Dapper,还可以检查my library,该enter image description here可以用于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在多个表之间映射查询数据。