我的项目分层如下:DAL (Entity)
-> BLL (DTO)
-> ApplicationComponent (ViewModel)
。
应用程序(ApplicationComponent
)将有多个组件,这些组件将访问BLL
。组件包括Windows服务,Web服务,Web API和MVC控制器。
我将NHibernate
Entity
对象转换为DTO
对象,同时将它们从DAL
传递到BLL
。在将此状态传递给ApplicationComponent
时,BLL
再次将其转换为ViewModel
。
这可以帮助我区分关注点以及在每一层中如何处理数据。由于以下原因,我不赞成返回NHibernate
Entity
对象进行查看:-
数据暴露给我要隐藏的UI
(或仅在需要时才暴露),例如密码,用户类型,权限等。
在引用/联接上,访问属性时,NHibernate
将执行其他查询,这将使延迟加载的使用无效。
暴露给用户(Entity
的)的不必要数据会造成错误的混淆和漏洞。
持久性实现泄漏到BLL
/ UI
中。 Entity
不是为UI
设计的。它不能在所有情况下都提供UI
服务。
我们将DTO
属性上的属性用于用户输入验证,对于Entity
来说看起来很奇怪。
我使用这种方法面临以下问题:-
最大和明显的问题是具有相似成员和功能的冗余对象。
我必须在每一层中编写映射器方法以转换对象。可以通过使用AutoMapper
或类似的方法将其最小化。但是它不能完全解决问题。
问题:-
是否过度分离,应避免(至少将其最小化)?
如果这种方法是正确的,我看不出有任何简单的方法可以完全绕开我上面提到的两个问题。请提出建议。
如果此方法不正确,请提出更正建议。
参考文献:
Link1建议转移Entity
对象以查看,据我所知这不是一个好主意。
Link2建议将Entity
与我已经在做的DTO
映射。
Link3没有帮助。
Link4建议使用类似“自动映射器”工具的工具。但是它仍然不能完全解决问题。
Link5是很棒的帖子。它解释了为什么我应该同意将它们分开。它没有评论如何最大程度地减少由此引起的开销。
Link6不再有用。
Link7是一个很好的答案,建议尽可能使用Entity
。它仍然不适用于我的大多数项目。
Linl8是另一个极好的资源,建议像我现在所做的那样以两种方式进行映射。它仍然没有建议最小化开销的方法。
参考方案
您是否考虑过在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; }
}
}
Spring Data Cassandra的事务管理 - java我正在使用Spring和Cassandra作为基础数据库。曾提到过弹簧伞项目“ spring data cassandra”。与休眠不同,在这里无法找到如何管理事务。如果您中的某些人已经合并,请共享要包含的事务管理器的详细信息。 参考方案 Cassandra不支持传统(ACID)的事务。在某些特殊情况下,可以通过一些构造来实现事务原子性,例如原子批处理(请参…
从Azure Data Factory执行python脚本 - python有人可以帮我从Azure数据工厂执行python函数吗?我已经将python函数存储在blob中,并且我试图触发同样的功能。但是我无法做到这一点。请协助。第二,我可以从ADF参数化python函数调用吗? python参考方案 您可能会发现ADF中的Azure Function Activity概念,它允许您在Data Factory管道中运行Azure F…
自动更新ext.data.store上的新数据 - php我有这个extjs数据存储 mystore= Ext.create('Ext.data.Store', { id: 'store_id', fields: ['label', 'value', 'id', 'type'], autoLoad…
如何使用Spring Data JPA更新实体中的集合字段? - java假设我有两个实体,它们的字段之间具有@ManyToMany关系。第一个实体称为Pack:@ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL}) @JoinTable(name = "card_in_pack", joinColumns = {@JoinColumn…
更新System.Data.SQLite.dll后,SQLite无效URI - c#我首先有以下SQLite版本:1.0.77.0(sqlite-netFx40-static-binary-bundle-Win32-2010-1.0.77.0)而且一切正常。将System.Data.SQLite.dll更新到版本1.0.82.0(sqlite-netFx40-static-binary-bundle-Win32-2010-1.0.82.0)…