洋葱模式.Net核心相关实体

时间:2019-01-29 16:44:57

标签: asp.net-core onion-architecture

我试图了解.net核心中的洋葱架构模式。给定下面的Github示例项目,您将如何包括相关实体?例如,在GamesController中,您还将如何返回相关的平台实体?由于每个服务都绑定到实体存储库

https://github.com/CubicleJockey/OnionPattern

    /// <summary>
    /// Get a list of all games.
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    [Route("all")]
    public IActionResult Get()
    {
        return ExecuteAndHandleRequest(() => GameRequestAggregate.GetAllGamesRequest.Execute());
    }



    public class GameRequestAggregate : BaseRequestAggregate<Domain.Game.Entities.Game>, IGameRequestAggregate
        {

            public GameRequestAggregate(IRepository<Domain.Game.Entities.Game> repository, IRepositoryAggregate repositoryAggregate) 
                : base(repository, repositoryAggregate)  {}

            #region Implementation of IGameRequestAggregate

            private ICreateGameRequest createGameRequest;
            public ICreateGameRequest CreateGameRequest => createGameRequest ?? (createGameRequest = new CreateGameRequest(Repository, RepositoryAggregate));

            private IDeleteGameByIdRequest deleteGameByIdRequest;
            public IDeleteGameByIdRequest DeleteGameByIdRequest =>deleteGameByIdRequest ?? (deleteGameByIdRequest = new DeleteGameByIdRequest(Repository, RepositoryAggregate));

            private IGetAllGamesRequest getAllGamesRequest;
            public IGetAllGamesRequest GetAllGamesRequest => getAllGamesRequest ?? (getAllGamesRequest = new GetAllGamesRequest(Repository, RepositoryAggregate));

            #endregion
        }




public class GetAllGamesRequest : BaseServiceRequest<Domain.Game.Entities.Game>, IGetAllGamesRequest
    {
        public GetAllGamesRequest(IRepository<Domain.Game.Entities.Game> repository, IRepositoryAggregate repositoryAggregate) 
            : base(repository, repositoryAggregate) { }


        #region Implementation of IGetAllGamesRequest

        public GameListResponse Execute()
        {
            Log.Information("Retrieving Games List...");
            var gameListResponse = new GameListResponse();
            try
            {
                var games = Repository.GetAll()?.ToArray();

                if (games == null || !games.Any())
                {
                    var exception = new Exception("No Games Returned.");
                    Log.Error(EXCEPTION_MESSAGE_TEMPLATE, exception.Message);
                    HandleErrors(gameListResponse, exception, 404);
                }
                else
                {
                    gameListResponse = new GameListResponse
                    {
                        Games = games,
                        StatusCode = 200
                    };
                    var count = games.Length;
                    Log.Information("Retrieved [{Count}] Games.", count);
                }

1 个答案:

答案 0 :(得分:3)

链接回购协议是高度过度设计的,而坦率地天真是为此设计的。创建多个项目并不等同于“洋葱体系结构”,并且到处都有依赖关系。洋葱架构的整个概念是具有 true 层。输入在层之间流入和流出,并且没有交叉。看起来贡献者正在刺杀CQRS,但失败相当惨。

对于您的特定问题,在使用存储库的特定设置中存在致命的缺陷。不幸的是,有太多的开发人员这样做,贡献者未能意识到使用EF等ORM时,您的数据层。在此之上创建一个单独的抽象只会导致问题,除非您复制EF所做的所有事情,例如联接,更改跟踪,对象修复等。当然,当您这样做时,基本上重新实施了EF。在您的应用程序和EF之间放置一个简单的存储库之类的东西实际上仅用于限制您可以对数据执行的操作,当然,在这种情况下,这就是您无法在没有大量过度查询的情况下加入相关实体的问题

如果您想真正抽象您的数据依赖关系,那么CQRS和微服务模式是您的最佳选择。 CQRS是一个非常复杂的主题,但它实质上可以归结为构建执行特定功能的“命令”,并着眼于创建事件驱动的模型。我鼓励您更多地研究该主题,但我会说,正确设置所有主题的努力实际上仅在大型企业级应用程序中才有意义。鉴于微服务模式的兴起,尤其如此。

微服务本质上是很小的API。它们通常实现为基于REST的Web API,但不一定必须如此。无论如何,您的想法是您将执行特定任务的端点返回特定数据。他们应该专注于应用功能的离散单元。例如,一个电子商务站点可能具有产品服务,购物车服务,付款处理/结帐服务,订单服务等。每个组件都利用这些微服务中的一个或多个来完成某些任务。通常涉及一个或多个API网关,以协调多个微服务的活动。这听起来可能有点复杂,但是实际上设置起来相当容易,尤其是如果您已经熟悉构建基于REST的API的话。最艰难的举动是协调服务以完成特定工作。这种模式还具有高度可伸缩性的优点。由于每个微服务都是离散且抽象的,因此您可以轻松地负载平衡和/或创建集群。而且,在云环境中,您可以根据流量轻松地放大或缩小。如果您的站点在某个区域受到重创,那么您只需启动更多正在运行的微服务实例,而当流量减少时,您便将它们降低。

最后,我将向您提供一些我必须学习的艰难建议:从小处着手。有一种动力要“正确”地做事情,并因此从一开始就实现各种模式和建筑风格。这样的结果是,您通常会陷入模式地狱,而从不真正地构建,即,您有一个非常复杂的设置,需要花费数周或数月的时间进行开发,而实际上并没有真正的用途显示它。

相反,以最简单直接的方法构建最小的功能单元。然后,转到下一个。每次迭代后,您应该有一些可以实际工作的东西。您将继续执行此操作,直到您构建了核心功能。它可能并不漂亮,但是可以完成任务。然后,您进行重构:如果您已重用了一些代码,请将其分解出来。如果您有相似但略有不同的代码,请首先找到方法对其进行概括。事情开始变得抽象,您可能会发现需要创建类库等。随着时间的流逝,您可能最终会构建一个包含各种层和抽象的真正复杂的设置,但这并不是100%的起点。