我的项目分层如下:-
DAL (Entity)
--> BLL (DTO)
--> ApplicationComponent (ViewModel)
.
应用程序将有多个组件(ApplicationComponent
)将访问BLL
。组件包括 Windows 服务、Web 服务、Web API 和 MVC 控制器。
我正在转变NHibernate
Entity
反对DTO
传递对象时DAL
to BLL
。当将此状态传递给ApplicationComponent
, BLL
再次将其转换为ViewModel
.
这有助于我区分关注点以及每一层中数据的处理方式。我不赞成退货NHibernate
Entity
出于以下原因拒绝查看:-
- 数据暴露于
UI
我想隐藏(或仅在需要时公开),例如密码、用户类型、权限等。
- 关于引用/连接,
NHibernate
访问属性时执行额外的查询,从而使延迟加载无效。
- 向用户(的
Entity
) 造成混乱和错误间隙。
- 持久性实现泄漏到
BLL
/UI
. Entity
不是为UI
。它无法服务UI
在所有情况下。
- 我们使用属性
DTO
用户输入验证的属性看起来很奇怪Entity
.
我使用这种方法面临以下问题:-
- 最大且明显的问题是具有相似成员和功能的冗余对象。
- 我必须在每一层编写映射器方法来转换对象。这可以通过使用最小化
AutoMapper
或类似的东西;但它并不能完全解决问题。
问题:-
- 这是过度分离吗?应该避免(至少最小化)吗?
- 如果这种方法是正确的,我看不出有任何简单的方法可以完全绕过我上面提到的两个问题。请建议。
- 如果此方法不正确,请提出更正建议。
参考:-
-
Link1 https://stackoverflow.com/questions/24261753/return-nhibernate-entity-from-web-api建议转
Entity
反对观点,在我看来这不是一个好主意。
-
Link2 https://stackoverflow.com/questions/9819615/which-is-the-best-practices-for-exposing-entity-or-dto-to-view-in-mvc3建议绘制地图
Entity
with DTO
我已经在做了。
-
Link3 https://stackoverflow.com/questions/13176707/static-methods-to-transform-dto-to-entity没有帮助。
-
Link4 https://stackoverflow.com/questions/7650616/how-to-map-persistent-objects-to-dto建议使用诸如自动映射器工具之类的东西,这是可以的。但仍然没有彻底解决问题。
-
Link5 https://stackoverflow.com/questions/4865806/why-two-classes-view-model-and-domain-model?rq=1很棒的帖子。它解释了为什么这些应该分开,我同意。它没有评论如何最小化由此造成的开销。
-
Link6 https://stackoverflow.com/questions/3094633/bestpractice-mixing-view-model-with-domain-model又没有帮助。
-
Link7 https://stackoverflow.com/questions/18109547/orm-entities-vs-domain-entities-under-entity-framework-6-0是一个很好的答案,建议使用
Entity
正如在UI
如果可能的话。它仍然不适用于我的大部分项目。
-
Linl8 https://stackoverflow.com/questions/2201150/should-i-map-a-dto-to-from-a-domain-entity-on-both-client-and-server-sides?rq=1是另一个优秀的资源,建议像我现在所做的那样继续以两种方式进行映射。它仍然没有提出一种最小化开销的方法。
您是否考虑过在 DTO 和实体之间创建共享接口?您不应该将 ORM 与应用程序的其余部分紧密耦合。或者实际上,如果可能的话,使用它们之间的接口以外的任何东西。
理论上,您可以有一个单独的项目,仅保存您期望传递的内容的合同/抽象。为了最大限度地减少映射开销并使其对扩展保持开放,您可以确保实体按预期实现接口(省略不需要的内容),并且在需要定制 DTO 的情况下,您可以使用接口创建带有映射的模型。
添加额外的接口项目时会产生一些开销,但从长远来看,它会让您的代码更干净、更易于维护。
namespace Data
{
public class FakeRepo : IFakeRepo
{
public IThisIsAnEntity GetEntity()
{
return new ThisIsAnEntity();
}
}
public class ThisIsAnEntity : IThisIsAnEntity
{
public string HiddenField { get; set; }
public long Id { get; set; }
public string SomeField { get; set; }
public string AnotherField { get; set; }
}
}
namespace Data.Abstractions
{
public interface IFakeRepo
{
IThisIsAnEntity GetEntity();
}
}
namespace Abstractions
{
public interface IThisIsAnEntity : IThisIsAnSlimmedDownEntity
{
string SomeField { get; set; }
}
public interface IThisIsAnSlimmedDownEntity
{
long Id { get; set; }
string AnotherField { get; set; }
}
}
namespace Services.Abstractions
{
public interface ISomeBusinessLogic
{
IThisIsAnEntity GetEntity();
IThisIsAnSlimmedDownEntity GetSlimmedDownEntity();
}
}
namespace Services
{
public class SomeBusinessLogic : ISomeBusinessLogic
{
private readonly IFakeRepo _repo;
public SomeBusinessLogic(IFakeRepo repo)
{
_repo = repo;
}
public IThisIsAnEntity GetEntity()
{
return _repo.GetEntity();
}
public IThisIsAnSlimmedDownEntity GetSlimmedDownEntity()
{
return _repo.GetEntity();
}
}
}
namespace UI
{
public class SomeUi
{
private readonly ISomeBusinessLogic _service;
public SomeUi(ISomeBusinessLogic service)
{
_service = service;
}
public IThisIsAnSlimmedDownEntity GetViewModel()
{
return _service.GetSlimmedDownEntity();
}
public IComposite GetCompositeViewModel()
{
var dto = _service.GetSlimmedDownEntity();
var viewModel = Mapper.Map<IThisIsAnSlimmedDownEntity, IComposite>(dto);
viewModel.SomethingSpecial = "Something else";
return viewModel;
}
}
public class SomeViewModel : IComposite
{
public long Id { get; set; }
public string AnotherField { get; set; }
public string SomethingSpecial { get; set; }
}
}
namespace UI.Abstractions
{
public interface IComposite : IThisIsAnSlimmedDownEntity, ISomeExtraInfo
{
}
public interface ISomeExtraInfo
{
string SomethingSpecial { get; set; }
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)