我应该将实体(持久)对象转换为 DTO 对象吗?

2024-02-24

我的项目分层如下:-

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或类似的东西;但它并不能完全解决问题。

问题:-

  1. 这是过度分离吗?应该避免(至少最小化)吗?
  2. 如果这种方法是正确的,我看不出有任何简单的方法可以完全绕过我上面提到的两个问题。请建议。
  3. 如果此方法不正确,请提出更正建议。

参考:-

  1. Link1 https://stackoverflow.com/questions/24261753/return-nhibernate-entity-from-web-api建议转Entity反对观点,在我看来这不是一个好主意。
  2. Link2 https://stackoverflow.com/questions/9819615/which-is-the-best-practices-for-exposing-entity-or-dto-to-view-in-mvc3建议绘制地图Entity with DTO我已经在做了。
  3. Link3 https://stackoverflow.com/questions/13176707/static-methods-to-transform-dto-to-entity没有帮助。
  4. Link4 https://stackoverflow.com/questions/7650616/how-to-map-persistent-objects-to-dto建议使用诸如自动映射器工具之类的东西,这是可以的。但仍然没有彻底解决问题。
  5. Link5 https://stackoverflow.com/questions/4865806/why-two-classes-view-model-and-domain-model?rq=1很棒的帖子。它解释了为什么这些应该分开,我同意。它没有评论如何最小化由此造成的开销。
  6. Link6 https://stackoverflow.com/questions/3094633/bestpractice-mixing-view-model-with-domain-model又没有帮助。
  7. Link7 https://stackoverflow.com/questions/18109547/orm-entities-vs-domain-entities-under-entity-framework-6-0是一个很好的答案,建议使用Entity正如在UI 如果可能的话。它仍然不适用于我的大部分项目。
  8. 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(使用前将#替换为@)

我应该将实体(持久)对象转换为 DTO 对象吗? 的相关文章

随机推荐