Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用RavenDB时,我应该将业务逻辑放在哪里_C#_.net_Nosql_<img Src="//i.stack.imgur.com/WM7S8.png" Height="16" Width="18" Alt="" Class="sponsor Tag Img">servicestack_Ravendb - Fatal编程技术网 servicestack,ravendb,C#,.net,Nosql,servicestack,Ravendb" /> servicestack,ravendb,C#,.net,Nosql,servicestack,Ravendb" />

C# 使用RavenDB时,我应该将业务逻辑放在哪里

C# 使用RavenDB时,我应该将业务逻辑放在哪里,c#,.net,nosql,servicestack,ravendb,C#,.net,Nosql,servicestack,Ravendb,我计划使用RavenDB作为我的数据存储构建一个单页应用程序(SPA) 我想从温泉浴巾的ASP.NET热毛巾模板开始 我将删除EntityFramework/WebApi/Breeze组件,并替换为RavenDB for storage和ServiceStack以构建后端API 大多数当前的观点似乎不赞成在RavenDB之上使用任何类型的存储库或额外的抽象,并呼吁直接在控制器内部使用RavendbAPI(在MVC应用程序中) 我假设在将Raven与ServiceStack一起使用时,我应该遵循同

我计划使用RavenDB作为我的数据存储构建一个单页应用程序(SPA)

我想从温泉浴巾的ASP.NET热毛巾模板开始

我将删除EntityFramework/WebApi/Breeze组件,并替换为RavenDB for storage和ServiceStack以构建后端API

大多数当前的观点似乎不赞成在RavenDB之上使用任何类型的存储库或额外的抽象,并呼吁直接在控制器内部使用RavendbAPI(在MVC应用程序中)

我假设在将Raven与ServiceStack一起使用时,我应该遵循同样的智慧,直接在我的服务实现中调用IDocumentSession

我担心的是,遵循这条路径,我的服务实现似乎会变得相当臃肿。似乎我还经常需要多次编写相同的代码,例如,如果我需要在几个不同的web服务端点内更新用户文档

似乎我还需要从我的应用程序的其他(未来)部分访问Raven。例如,我将来可能需要添加一个控制台应用程序来处理队列中的作业,这部分应用程序可能需要访问Raven中的数据……但从一开始,我到Raven的唯一路径就是通过web服务API。我是否打算从这个理论控制台应用程序调用web api?如果它们可能在同一个硬件上运行,那么它们似乎效率低下

在使用此文档库时,是否有人能提供有关如何在我的Web服务和其他地方有效利用Raven的建议,同时仍遵循最佳实践?创建一个直接处理针对raven的调用的中间业务逻辑层似乎是可行的……允许我的Web服务调用该层中的方法。这有意义吗

编辑


有人能提供类似建筑的最新样本吗?

这里有两个主要部分要考虑。

首先,正如您已经注意到的,如果您遵循更狂热的RavenDB粉丝的话,它是一种神话般的野兽,不受其他公认的良好应用程序设计法则的约束,应该允许它随意渗透到您的整个应用程序中

当然,这取决于具体情况,但简单地说,如果您想用SQL Server之类的东西以某种方式构造应用程序,那么对RavenDB也要这样做。如果您想在SQL Server后端使用DAL层、ORM、存储库模式或其他任何东西,请在RavenDB上也这样做。如果您不介意有漏洞的抽象,或者项目太小,根本无法保证对数据访问进行抽象,那么请相应地编写代码

RavenDB的主要区别在于,您可以获得一些东西,比如“免费”的工作单元和ORM,但总体解决方案架构应该没有那么大的不同


第二,连接其他客户。为什么控制台应用程序(或任何其他客户端)访问RavenDB服务器实例的方式与访问网站的方式有任何不同?即使在ASP.NET应用程序中运行服务器嵌入式模式,也可以使用相同的RavenDB.Client代码将其他客户端连接到它。您不需要直接接触web服务API。

FWIW,我们目前正在使用ServiceStack和RavenDB开发一个应用程序。我们正在使用DDD方法,并将业务逻辑置于丰富的域层中。架构是:

  • 网络应用。托管web客户端代码(SPA)和服务层

  • 服务层。使用ServiceStack的Web服务具有与域对象完全解耦的干净/相当平坦的DTO。Web服务负责管理事务和所有RavenDB交互。大多数“命令式”服务操作包括:a)加载由请求标识的域对象(文档),b)调用业务逻辑,c)将结果转换为响应DTO。我们已经扩展了ServiceStack,因此许多命令操作都使用了一个自动处理程序,可以在不需要任何代码的情况下完成上述所有操作。“查询ish”服务操作通常包括:a)对RavenDB执行查询,b)在查询处理/索引/转换器期间使用RavenDB将查询结果转换为响应DTO(实际上,这通常作为a的一部分)。业务逻辑总是下推到域层

  • 域层。与DDD中的“根聚合”相对应的文档完全不依赖于数据库。域对象只公开公共getter和私有setter。修改域对象状态的唯一方法是调用方法。域对象公开服务层使用的公共方法,或域层内使用的受保护/内部方法。域层引用消息程序集,主要是为了允许域对象上的方法接受复杂的请求对象,并避免使用长得令人痛苦的参数列表的方法

  • 消息程序集。用于支持其他本机.Net客户端(如单元测试和集成测试)的独立程序集

  • 至于其他客户,我们有两种选择。我们可以引用ServiceStack.Common和消息程序集并调用web服务。或者,如果需求有很大不同,我们希望绕过web服务,我们可以创建一个新的客户端应用程序,引用域层程序集和Raven客户端,并直接以这种方式工作

    在我看来,存储库模式是一种不必要的、漏洞百出的抽象。我们仍在开发中,但到目前为止,上述功能似乎运行良好

    编辑

    一个大大简化的域对象可能看起来像这样

    public class Order
    {
        public string Id { get; private set; }
        public DateTime Raised { get; private set; }
        public Money TotalValue { get; private set; }
        public Money TotalTax { get; private set; }
        public List<OrderItem> Items { get; private set; }
    
        // Available to the service layer.
        public Order(Messages.CreateOrder request, IOrderNumberGenerator numberGenerator, ITaxCalculator taxCalculator)
        {
            Raised = DateTime.UtcNow;
            Id = numberGenerator.Generate();
            Items = new List<OrderItem>();
            foreach(var item in request.InitialItems)
                AddOrderItem(item);
            UpdateTotals(taxCalculator);
        }
    
        private void AddOrderItemCore(Messages.AddOrderItem request)
        {
            Items.Add(new OrderItem(this, request));
        }
    
        // Available to the service layer.
        public void AddOrderItem(Messages.AddOrderItem request, ITaxCalculator taxCalculator)
        {
            AddOrderItemCore(request);
            UpdateTotals(taxCalculator);
        }
    
        private void UpdateTotals(ITaxCalculator taxCalculator)
        {
            TotalTax = Items.Sum(x => taxCalculator.Calculate(this, x));
            TotalValue = Items.Sum(x => x.Value);
        }
    }
    
    公共类秩序
    {
    公共字符串Id{get;private set;}
    引发的公共日期时间{get;private set;}
    公共Mo