我正在学习存储库模式和实体框架。我有一个关于如何使用EF 6 Code First(现有Db)映射我的类的问题。我知道有很多关于这个问题的问题(而且我已经把它们搞砸了)但是我仍然很难理解某些东西,这似乎是“逻辑”但它让我发疯(也许我已经引起了太多不同的意见) ...)
表Processes
,它存储不同的流程,如要约,收据,订单等。表格的一列是AddDate
,表示此流程何时添加到数据库。
现在我想编写一个库来访问这个数据库,以便在不同的应用程序中使用它,因为它是公司的核心 Db。
在库中,我希望公开一个ProcessRepository
,其方法为GetByAddDateRange
,它返回在给定时间范围之后,之前或之中添加的进程。
所以,现在使用CodeFirst到现有数据库的EF首先为每个表生成一个类,每个表都有一个属性。所以我有一个课程Process
(从现在开始ProcessEntity)
,其中包含一个属性AddDate
。
现在在我的“域模型”中,我想要在我的业务逻辑等中使用的类,我希望有一个类Process
(从现在开始ProcessDomain)
但是这不应该有{ {1}}属性,因为它对“对象”不重要或者是“属性”的一部分。
那么现在如果我想使用此AddDate作为条件从我的AddDate
获取ProcessDomains
,我该怎么办?
如果我直接使用ProcessRepository
作为“域模型”(由EF生成的类),如果我理解正确,我必须有一个名为ProcessEntity
的属性,因为我需要它在我的回购时,做某事如AddDate
还是没有?
我可以(就像我读过的那样)有一个类Return _dbContext.Set(Of Process).Where(Func(s)s.AddDate>addDate)
和ProcessEntity
,并在我的存储库中手动映射它们。如果我理解正确,repo应该返回上面层的预期类型,在这种情况下应该返回我的domainModel类。
所以对我来说,第一个选项似乎只是在所有场景中都没用,因为你必须在你的类中拥有特定的属性。因此,无论我如何尝试查看问题,我总是看到在使用现有数据库时需要手动映射。
也许我错过了某事或理解错误,所以请告诉我。
答案 0 :(得分:1)
您的EF实体需要拥有您要使用的所有数据库列的属性,其中包括您要过滤的那些列。这意味着与该表对应的EF类必须具有该AddDate
属性。如果你想要一个没有该属性的类,那么你需要定义另一个类。
无论如何,许多开发人员/团队都会这样做。我们在办公室里主要做ASP.NET MVC工作,我们有一个EF模型,它对应于从中返回类型的数据库和存储库,然后我们有一个服务层将这些EF实体映射到数据传输对象(DTO)。 DTO可以100%映射到相应的实体,但是它们也可能缺少一些属性和/或具有额外的属性。可能还存在与单个实体不对应的DTO。我们通常在应用程序和数据库之间使用Web服务,因此DTO与减少数据传输的效率一样高。
我们有自己的工具来生成基于EF模型的DTO。然后,我们将根据需要调整生成的代码。如果我们需要添加成员,我们通常在部分类中这样做,因此将来的重新生成不会影响该代码。如果我们需要删除成员,那么我们别无选择,只能编辑生成的代码。我们还使用AutoMapper在EF实体和DTO之间映射数据,反之亦然。
答案 1 :(得分:1)
选项1:
创建具有您真正想要的DTO。读/写时实体和DTO之间的映射。 (映射很繁琐且容易出错.AutoMapper有很多帮助。)
选项2:
在实体上使用DataContract / DataMember等属性来控制序列化哪些字段以及忽略哪些字段。
仍然容易出错,因为实体中充满了不必填充的集合。
选项3:
使用其他ORM。 Tortuga Chain专为与DTO和ViewModels配合使用而设计,无需将其映射到实体。