- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我几天来一直试图解决这个问题,但关于 ASP.NET MVC 这个特定主题的信息似乎很少。我已经在谷歌上搜索了好几天了,但还没有真正弄清楚这个特定问题的任何信息。
我有一个 3 层项目。业务、DAL 和 UI/Web 层。 DAL 中包含 dbcontext、存储库和工作单元。业务层是一个包含所有接口(interface)和 EF 模型的领域层。在业务层中,还有一个服务层,其中包含用于 EF 模型的 DTO 和访问存储库的通用存储库服务。 This图片应该有助于解释它。
我的问题是,我似乎无法弄清楚如何使用 DTO 从业务层传输数据。
我已经为 DTO 创建了服务类。我有一个 ImageDTO 和模型,图像 anchor 也是如此。我为每个 DTO 创建了一个服务类。所以我有图像服务和主播服务。这些服务继承了存储库服务,并且目前实现了自己的服务。但这就是我所了解到的。由于这些服务具有通过 IoC 接收 IUnitOfWork 接口(interface)的构造函数,我几乎陷入了困境。
如果我直接从 UI 引用服务,一切都会正常工作,但我就是不知道如何使用 DTO 将数据从服务层传输到 UI 层,以及相反。
我的服务层:
业务/服务/DTO
public class AnchorDto
{
public int Id { get; set; }
public int x1 { get; set; }
public int y1 { get; set; }
public int x2 { get; set; }
public int y2 { get; set; }
public string description { get; set; }
public int imageId { get; set; }
public int targetImageId { get; set; }
public AnchorDto(int Id, int x1, int y1, int x2, int y2, string description, int imageId, int targetImageId)
{
// Just mapping input to the DTO
}
}
public class ImageDto
{
public int Id { get; set; }
public string name { get; set; }
public string title { get; set; }
public string description { get; set; }
public virtual IList<AnchorDto> anchors { get; set; }
public ImageDto(int Id, string name, string title, string description, IList<AnchorDto> anchors )
{
// Just mapping input to DTO
}
}
业务/服务/服务
public class RepoService<TEntity> : IRepoService<TEntity> where TEntity : class
{
private IRepository<TEntity> repo;
public RepoService(IUnitOfWork repo)
{
this.repo = repo.GetRepository<TEntity>();
}
public IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
return repo.Get(filter, orderBy, includeProperties);
}
public TEntity GetByID(object id)
{
return repo.GetByID(id);
}
public void Insert(TEntity entity)
{
repo.Insert(entity);
}
public void Delete(object id)
{
repo.Delete(id);
}
public void Delete(TEntity entityToDelete)
{
repo.Delete(entityToDelete);
}
public void Update(TEntity entityToUpdate)
{
repo.Update(entityToUpdate);
}
}
图像服务,IImageService 接口(interface)目前是空的,直到我弄清楚我需要实现什么。
public class ImageService : RepoService<ImageModel>, IImageService
{
public ImageService(IUnitOfWork repo)
: base(repo)
{
}
}
目前我的 Controller 并没有真正工作并且没有使用服务层,所以我决定不包含其中的任何一个。我计划在解决此问题后使用自动映射器将 DTO 映射到 ViewModel。
现在,请任何有足够知识的人告诉我我所缺少的想法,以便我能弄清楚这一点?
最佳答案
您的服务应该接收 DTO,将它们映射到业务实体并将它们发送到存储库。它还应该从存储库中检索业务实体,将它们映射到 DTO 并返回 DTO 作为响应。因此,您的业务实体永远不会脱离业务层,只有 DTO 才能脱离业务层。
那么你的 UI\Weblayer 应该不知道业务实体。 Web 层应该只知道 DTO。执行此规则非常重要,您的 UI 层不使用服务实现类(应该是私有(private)的),而仅使用接口(interface)。并且服务接口(interface)不应该依赖于业务实体,而只依赖于 DTO。
因此,您需要基于 DTO 的服务接口(interface),并且您的基服务类需要 DTO 的另一个通用参数。我喜欢为实体和 DTO 提供一个基类,这样它们就可以声明为:
//Your UI\presentation layer will work with the interfaces (The inheriting ones)
//so it is very important that there is no dependency
//on the business entities in the interface, just on the DTOs!
protected interface IRepoService<TDto>
where TDto: DTOBase
{
//I'm just adding a couple of methods but you get the idea
TDto GetByID(object id);
void Update(TDto entityToUpdateDto)
}
//This is the interface that will be used by your UI layer
public IImageService: IRepoService<ImageDTO>
{
}
//This class and the ones inheriting should never be used by your
//presentation\UI layer because they depend on the business entities!
//(And it is a best practice to depend on interfaces, anyway)
protected abstract class RepoService<TEntity, TDto> : IRepoService<TDto>
where TEntity : EntityBase
where TDto: DTOBase
{
...
}
//This class should never be used by your service layer.
//Your UI layer should always use IImageService
//You could have a different namespace like Service.Implementation and make sure
//it is not included by your UI layer
public class ImageService : RepoService<ImageModel, ImageDto>, IImageService
{
...
}
然后,您需要一种将实体和 DTO 之间的映射添加到该基本服务的方法,而无需实际实现映射(因为它取决于每个具体实体和 DTO 类)。您可以声明执行映射的抽象方法,并且需要在每个特定服务(例如 ImageService
)上实现。基本 RepoService 的实现如下所示:
public TDto GetByID(object id)
{
//I'm writing it this way so its clear what the method is doing
var entity = repo.GetByID(id);
var dto = this.EntityToDto(entity);
return dto;
}
public void Update(TDto entityToUpdateDto)
{
var entity = this.DtoToEntity(entityToUpdateDto)
repo.Update(entity);
}
//These methods will need to be implemented by every service like ImageService
protected abstract TEntity DtoToEntity(TDto dto);
protected abstract TDto EntityToDto(TEntity entity);
或者您可以声明映射服务,添加对 IOC 应该提供的适当映射服务的依赖关系(如果您需要在不同服务上使用相同的映射,这更有意义)。 RepoService 的实现如下所示:
private IRepository<TEntity> _repo;
private IDtoMappingService<TEntity, TDto> _mappingService;
public RepoService(IUnitOfWork repo, IDtoMappingService<TEntity, TDto> mapping)
{
_repo = repo.GetRepository<TEntity>();
_mappingService = mapping;
}
public TDto GetByID(object id)
{
//I'm writing it this way so its clear what the method is doing
var entity = repo.GetByID(id);
var dto = _mappingService.EntityToDto(entity);
return dto;
}
public void Update(TDto entityToUpdateDto)
{
var entity = _mappingService.DtoToEntity(entityToUpdateDto)
repo.Update(entity);
}
//You will need to create implementations of this interface for each
//TEntity-TDto combination
//Then include them in your dependency injection configuration
public interface IDtoMappingService<TEntity, TDto>
where TEntity : EntityBase
where TDto: DTOBase
{
public TEntity DtoToEntity(TDto dto);
public TDto EntityToDto(TEntity entity);
}
在这两种情况下(抽象方法或映射服务),您都可以手动或使用 Automapper 等工具实现实体和 DTO 之间的映射。 。但是在使用 AutoMapper 和 Entity Framework 时你应该非常小心,尽管那是另一个话题了! (谷歌一下并收集有关该主题的一些信息。作为第一个建议,请注意加载数据时针对数据库执行的查询,这样您就不会加载超出需要的内容或发送许多查询。保存数据时请注意您的收藏和关系)
帖子可能很长,但希望对您有所帮助!
关于asp.net-mvc - 使用DTO在服务层和UI层之间传输数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16866102/
我一直在做一些关于测量数据传输延迟的实验 CPU->GPU 和 GPU->CPU。我发现对于特定消息大小,CPU->GPU 数据传输速率几乎是 GPU->CPU 传输速率的两倍。谁能解释我为什么会这样
我将 ElasticSearch 用作我的 Post 模型的 Rails pet 项目应用程序的全文引擎。在我的 posts_controller.rb 索引操作中: def index
概述 流经网络的数据总是具有相同的类型:字节,这些字节如何传输主要取决于我们所说的网络传输。用户并不关心传输的细节,只在乎字节是否被可靠地发送和接收 如果使用 Java 网络编程,你会发现,某些时候当
我正在编写一些代码,以便将共享点从该页面转移到另一个页面: Server.Transfer("/DefectManagement/DefectList/default.aspx") 但是我遇到了这个问
我有这个泄漏,任何猜测?这个类有一些奇怪的引用。我的代码的任何地方都没有 contentobserver In com.example:1.5.0:27. com.example.ui.record
我听说过点对点内存传输并阅读了一些关于它的内容,但无法真正理解与标准 PCI-E 总线传输相比它的速度有多快。 我有一个使用多个 GPU 的 CUDA 应用程序,我可能对 P2P 传输感兴趣。我的问题
ftping 文件时,Transmit 中是否有忽略或过滤器列表?我希望它忽略上传 .svn 文件等。 最佳答案 是的。转到首选项并选择 Rules标签。在那里您可以定义要跳过哪些文件的规则。实际上,
我有以下片段来生成声音,在 while 循环中,我想动态更改它,以便它在声音生成期间创建不同频率的声音。 for(uint16_t i = 0; i < sample_N; i++) { da
我正在尝试使用 Delphi 2010 和 Indy 对 Web 服务进行概念验证。我此时的代码是: procedure TForm1.Log(const sEvent, sMsg: String);
我有一个 ActiveMQ JMS 代理,在端口 61616 上使用默认的 openwire TCP 传输公开。 我有许多远程客户端可以绑定(bind)到此代理来监听他们的消息。 如果我想打开 kee
reconnection strategies文档仅使用 JMS 示例,但是 FTP transport documentation确实说明了重新连接策略的使用,但没有任何细节或示例。 进一步,如果你
我有 2 个 TreeView,第一个填充有项目。 try { CheckBoxTreeItem treeRoot = new CheckBoxTreeItem("Root"); tr
在我为学校开发的一个网站上,用户输入他们的学校电子邮件和密码,如果他们已注册,则登录。如果没有,则会显示登录的第二部分,要求输入笔名称并确认密码。正因为如此,以及我复杂的业余 Django 编程,我有
我正在开发一个 Web 服务,我们在其中使用 LINQ-to-SQL 进行数据库抽象。当客户使用我们的网络服务时,对象被序列化为 XML,一切都很好。 现在我们希望开发我们自己的使用本地数据类型的客户
我应该创建一个名为“Backwards”的方法,该方法将列表从尾部横向到头部,但是当我运行代码时,它出现说(第 88 行)它找不到光标 = cusor.prev;象征。我需要在循环中再次设置上一个链接
给定像 Uint8Array 这样的类型化数组,似乎有两种方法可以通过 worker 传输它们。 选项 1 直接发送缓冲区并在接收端进行转换: 发件人:postMessage({fooBuffer:
在 PHP + jQuery 环境中,我和我的 friend 无法得出最佳解决方案。我们正在使用 Ajax 从数据库中获取数据。 解决方案 1 - Ajax 应该只传输数据,而不是 HTML 好处:我
大家好,非常感谢您的宝贵时间。 有一个 std::stringstream 需要传输到远程机器。网络库允许我用以下方法构建数据包: CreatePacket( const void * DATA, s
我正在使用 libcurl 通过 FTP 传输二进制文件 (.exe),并将其保存到本地文件。问题是文件传输后,它已被更改,不再是有效的 Win32 应用程序,因此无法运行。这是我的做法: CURL
各位程序员, 当我将它上传到我的 FTP 时,我的网站出现此错误:资源被解释为样式表,但使用 MIME 类型文本/纯文本传输 BlahBlahi
我是一名优秀的程序员,十分优秀!