連千荣 發表於 2023-4-13 13:36:00

基于SqlSugar的开发框架循序渐进介绍(27)-- 基于MongoDB的数据库操作整合

<p>SqlSugar的开发框架本身主要是基于常规关系型数据库设计的框架,支持多种数据库类型的接入,如SqlServer、MySQL、Oracle、PostgreSQL、SQLite等数据库,非关系型数据库的MongoDB数据库也可以作为扩展整合到开发框架里面,通过基类的继承关系很好的封装了相关的基础操作功能,极大的减少相关处理MongoDB的代码,并提供很好的开发效率。本篇随笔介绍如何在SqlSugar的开发框架整合MongoDB数据库的开发。</p>
<h3>1、MongDB的简单介绍</h3>
<p>MongoDB是一款由C++编写的高性能、开源、无模式的常用非关系型数据库产品,是非关系数据库当中功能最丰富、最像关系数据库的数据库。它扩展了关系型数据库的众多功能,例如:辅助索引、范围查询、排序等。&nbsp;</p>
<p>MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似Json的Bson格式,因此可以存储比较复杂的数据类型。<br>MongoDB 最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。并且MongoDB-4.2版本开始已经支持分布式事务功能。</p>
<p>MongoDB数据库有几个简单的概念需要了解一下。</p>
<p>&nbsp; &nbsp; 1)MongoDB中的&nbsp;<code>database</code>&nbsp;有着和我们熟知的"数据库"一样的概念 (对 Oracle 来说就是 schema)。一个 MongoDB 实例中,可以有零个或多个数据库,每个都作为一个高等容器,用于存储数据。</p>
<p>&nbsp; &nbsp; 2)数据库中可以有零个或多个&nbsp;<code>collections</code>&nbsp;(集合)。集合和传统意义上的 table 基本一致,可以简单的把两者看成是一样的东西。</p>
<p>&nbsp; &nbsp; 3)集合是由零个或多个&nbsp;<code>documents</code>&nbsp;(文档)组成。同样,一个文档可以看成是一&nbsp;<code>row</code>。</p>
<p>&nbsp; &nbsp; 4)文档是由零个或多个&nbsp;<code>fields</code>&nbsp;(字段)组成。,对应的就是关系数据库的&nbsp;<code>columns</code>。</p>
<p>&nbsp; &nbsp; 5)<code>Indexes</code>&nbsp;(索引)在 MongoDB 中扮演着和它们在 RDBMS 中一样的角色,都是为了提高查询的效率。</p>
<p>&nbsp; &nbsp; 6)<code>Cursors</code>&nbsp;(游标)和上面的五个概念都不一样,但是它非常重要,并且经常被忽视,其中最重要的你要理解的一点是,游标是当你问 MongoDB 拿数据的时候,它会给你返回一个结果集的指针而不是真正的数据,这个指针我们叫它游标,我们可以拿游标做我们想做的任何事情,比如说计数或者跨行之类的,而无需把真正的数据拖下来,在真正的数据上操作。</p>
<p>&nbsp;它们的对比关系图如下所示。</p>
<p><img src="http://www.codeproject.com/KB/database/1037052/image002.png" alt="" width="364" height="212" class="medium-zoom-image"></p>
<p>数据在Mongodb里面都是以Json格式方式进行存储的,如下所示是其中的一个记录内容。</p>
<p><strong>BSON格式</strong></p>
<p>Bson是一种类Json的一种二进制形式的存储格式,简称Binary Json,它和Json一样,支持内嵌的文档对象和数组对象,但是Bson有Json没有的一些数据类型,如Date和BinData类型。</p>
<p>Bson可以做为网络数据交换的一种存储形式,这个有点类似于Google的Protocol&nbsp;Buffer,但是Bson是一种schema-less的存储形式,它的优点是灵活性高,但它的缺点是空间利用率不是很理想,Bson有三个特点:轻量性、可遍历性、高效性,</p>
<p>{“hello":"world"} 这是一个Bson的例子,其中"hello"是key name,它一般是cstring类型,字节表示是cstring::= (byte*) "/x00" ,其中*表示零个或多个byte字节,/x00表示结束符;后面的"world"是value值,它的类型一般是string,double,array,binarydata等类型。</p>
<p>MongDB数据库本身支持多种开发语言的驱动,MongoDB有官方的驱动如下:</p>
<p><img src="https://img2023.cnblogs.com/blog/8867/202304/8867-20230413120026055-1746825806.png" alt="" width="566" height="256" loading="lazy"></p>
<p>我们框架基于C#开发,使用的时候,安装MongoDB的C#的驱动&nbsp;MongoDB.Driver&nbsp;即可。</p>
<p><img src="https://img2023.cnblogs.com/blog/8867/202304/8867-20230413121452068-898319214.png" alt="" width="500" height="130" loading="lazy"></p>
<p>在MongoDB数据库的集合里面,都要求文档有一个_id字段,这个是强制性的,而且这个字段的存储类型为ObjectId类型,这个值考虑了分布式的因素,综合了机器码,进程,时间戳等等方面的内容,它的构造如下所示。</p>
<p><img src="https://img2023.cnblogs.com/blog/8867/202304/8867-20230413122346880-1117601650.png" alt=""></p>
<p>ObjectId是一个12字节的&nbsp;&nbsp;BSON&nbsp;类型字符串。按照字节顺序,依次代表:</p>
<ul>
<li>4字节:UNIX时间戳</li>
<li>3字节:表示运行MongoDB的机器</li>
<li>2字节:表示生成此_id的进程</li>
<li>3字节:由一个随机数开始的计数器生成的值</li>





</ul>
<p><img src="https://images2015.cnblogs.com/blog/8867/201601/8867-20160105093240950-2112739981.png" alt="" class="medium-zoom-image"></p>
<p>实体基类一般包含了一个属性Id,这个是一个字符串型的对象(也可以使用ObjectId类型,但是为了方便,我们使用字符型,并声明为ObjectId类型即可),由于我们声明了该属性对象为ObjectId类型,那么我们就可以在C#代码里面使用字符串的ID类型了。</p>
<p>&nbsp;</p>
<h3>2、基于MongoDB数据库的封装处理</h3>
<p>以前介绍过,针对常规关系型数据库的开发,在SqlSugar开发框架上,我们设计一些基类,以便重用相关的逻辑代码,通过泛型的约束,可以提供强类型的数据接口,非常方便。</p>
<p><img src="https://img2023.cnblogs.com/blog/8867/202304/8867-20230413122324629-2003339446.png" alt="" width="550" height="406" loading="lazy"></p>
<p>其中MyCrudService里面封装了很多CRUD以及常用的处理方法。类似的处理方式,我们专门为MongoDB数据库的访问操作,设计了一个功能强大的基类即可。</p>
<p><img src="https://img2023.cnblogs.com/blog/8867/202304/8867-20230413122422946-827015218.png" alt="" width="550" height="502" loading="lazy"></p>
<p>在数据库表的实体对应关系上,我们依旧遵循则相应的设计规则,基类实体采用IEntity&lt;string&gt;的接口类型,因此他们具有一个字符串的Id类型。其他业务对象继承该基类对象即可。</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 基于MongoDB的实体类基类
    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> BaseMongoEntity : Entity&lt;<span style="color: rgba(0, 0, 255, 1)">string</span>&gt;<span style="color: rgba(0, 0, 0, 1)">
    {
       <span style="color: rgba(255, 0, 0, 1)"><strong> </strong></span>
       <span style="color: rgba(255, 0, 0, 1)">
      </span></span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">override</span> <span style="color: rgba(0, 0, 255, 1)">string</span> Id { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
    }</span></pre>
</div>
<p>相应的,我们根据常规数据库的基类接口名称,在处理MongoDB数据库的操作接口的时候,名称保持一致性。</p>
<p>其中TEntity为强类型实体类型,而TGetListInput 是定义的一个分页接口。定义的基类接口代码如下所示。</p>
<p><img src="https://img2023.cnblogs.com/blog/8867/202304/8867-20230413122657005-277678240.png" alt="" width="1188" height="577" loading="lazy"></p>
<p>其中接口对象 CurrentApiUser是我们用户上下文的信息,包含一些驻留在ClainPrincipal中的信息,用于记录访问接口的用户信息的。</p>
<p>其他接口定义类似的处理即可。</p>
<p>基类接口的实现类,就是我们需要设计的MongoDB数据库操作类了,初始化类的代码如下所示。</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> MongoDB基础仓储实现
    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;typeparam name="TEntity"&gt;&lt;/typeparam&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">abstract</span> <span style="color: rgba(0, 0, 255, 1)">class</span> <strong><span style="color: rgba(255, 0, 0, 1)">BaseMongoService</span></strong>&lt;TEntity, TGetListInput&gt; : <span style="color: rgba(255, 0, 0, 1)"><strong>IBaseMongoService</strong></span>&lt;TEntity, TGetListInput&gt;
      <span style="color: rgba(0, 0, 255, 1)">where</span> TEntity : <span style="color: rgba(0, 0, 255, 1)">class</span>, IEntity&lt;<span style="color: rgba(0, 0, 255, 1)">string</span>&gt;, <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">()
      </span><span style="color: rgba(0, 0, 255, 1)">where</span><span style="color: rgba(0, 0, 0, 1)"> TGetListInput : IPagedAndSortedResultRequest
    {
      </span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">readonly</span> IMongoDBContext mongoContext = <span style="color: rgba(255, 0, 0, 1)">NullMongoDBContext.Instance</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">空实现</span>
      <span style="color: rgba(0, 0, 255, 1)">protected</span> IMongoCollection&lt;TEntity&gt; <span style="color: rgba(255, 0, 0, 1)"><strong>collection</strong></span>;         <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">强类型对象集合</span>
      <span style="color: rgba(0, 0, 255, 1)">protected</span> IMongoCollection&lt;BsonDocument&gt; <strong><span style="color: rgba(255, 0, 0, 1)">bsonCollection</span></strong>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">弱类型集合BsonDocument集合</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 当前Api用户信息
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> IApiUserSession CurrentApiUser { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span>; } = NullApiUserSession.Instance;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">空实现</span>

      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 构造函数
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">protected</span><span style="color: rgba(0, 0, 0, 1)"> BaseMongoService()
      {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如果SerivcePovider已经设置值,则获得注入的接口对象</span>
            <span style="color: rgba(0, 0, 255, 1)">if</span> (ServiceLocator.SerivcePovider != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
            {
                CurrentApiUser </span>= ServiceLocator.GetService&lt;IApiUserSession&gt;<span style="color: rgba(0, 0, 0, 1)">();
                mongoContext </span>= ServiceLocator.GetService&lt;IMongoDBContext&gt;<span style="color: rgba(0, 0, 0, 1)">();
                collection </span>= mongoContext.GetCollection&lt;TEntity&gt;(<span style="color: rgba(0, 0, 255, 1)">typeof</span>(TEntity).Name);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">强类型对象集合</span>
                bsonCollection = mongoContext.GetCollection&lt;BsonDocument&gt;(<span style="color: rgba(0, 0, 255, 1)">typeof</span>(TEntity).Name);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">弱类型集合BsonDocument集合</span>
<span style="color: rgba(0, 0, 0, 1)">            }
      }
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 获取所有记录
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;returns&gt;&lt;/returns&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">virtual</span> <span style="color: rgba(0, 0, 255, 1)">async</span> Task&lt;ListResultDto&lt;TEntity&gt;&gt;<span style="color: rgba(0, 0, 0, 1)"> GetAllAsync()
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> all = <span style="color: rgba(0, 0, 255, 1)">await</span> collection.FindAsync(Builders&lt;TEntity&gt;<span style="color: rgba(0, 0, 0, 1)">.Filter.Empty);
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> list = <span style="color: rgba(0, 0, 255, 1)">await</span><span style="color: rgba(0, 0, 0, 1)"> all.ToListAsync();
            </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> ListResultDto&lt;TEntity&gt;<span style="color: rgba(0, 0, 0, 1)">()
            {
                Items </span>=<span style="color: rgba(0, 0, 0, 1)"> list
            };
      }</span></pre>
</div>
<p>我们通过构建对应的强类型Collection和弱类型Collection,来操作实体类和BsonDocument的相关操作的。其中的上下文对象,参考随笔《NoSQL – MongoDB Repository Implementation in .NET Core with Unit Testing example》进行的处理。</p>
<div class="cnblogs_code">
<pre>   <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> MongoDB 上下文对象
    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MongoDBContext : IMongoDBContext
    {
      </span><span style="color: rgba(0, 0, 255, 1)">private</span> IMongoDatabase _db { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
      </span><span style="color: rgba(0, 0, 255, 1)">private</span> MongoClient _mongoClient { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
      </span><span style="color: rgba(0, 0, 255, 1)">public</span> IClientSessionHandle Session { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }

      </span><span style="color: rgba(0, 0, 255, 1)">public</span> MongoDBContext(<strong><span style="color: rgba(255, 0, 0, 1)">IOptions&lt;Mongosettings&gt;</span></strong><span style="color: rgba(0, 0, 0, 1)"> configuration)
      {
            _mongoClient </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MongoClient(configuration.Value.Connection);
            _db </span>=<span style="color: rgba(0, 0, 0, 1)"> _mongoClient.GetDatabase(configuration.Value.DatabaseName);
      }

      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 获取强类型集合对象
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;typeparam name="T"&gt;</span><span style="color: rgba(0, 128, 0, 1)">对象类型</span><span style="color: rgba(128, 128, 128, 1)">&lt;/typeparam&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="name"&gt;&lt;/param&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;returns&gt;&lt;/returns&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> IMongoCollection&lt;T&gt; GetCollection&lt;T&gt;(<span style="color: rgba(0, 0, 255, 1)">string</span> name) <span style="color: rgba(0, 0, 255, 1)">where</span> T : <span style="color: rgba(0, 0, 255, 1)">class</span>, <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">()
      {
            </span><span style="color: rgba(0, 0, 255, 1)">return</span> _db.GetCollection&lt;T&gt;<span style="color: rgba(0, 0, 0, 1)">(name);
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> IMongoDBContext
    {
      IMongoCollection</span>&lt;T&gt; GetCollection&lt;T&gt;(<span style="color: rgba(0, 0, 255, 1)">string</span> name) <span style="color: rgba(0, 0, 255, 1)">where</span> T : <span style="color: rgba(0, 0, 255, 1)">class</span>, <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">();
    }</span></pre>
</div>
<p>通过IOptions 方式我们注入对应的MongoDB数据库配置信息,在appsettings.json中添加根节点内容。</p>
<div class="cnblogs_code">
<pre>"<strong><span style="color: rgba(255, 0, 0, 1)">MongoSettings</span></strong>"<span style="color: rgba(0, 0, 0, 1)">: {
    </span>"Connection": "mongodb://localhost:27017/", <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">MongoDB连接字符串</span>
    "DatabaseName": "iqidi" <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">MongoDB数据库名称</span>
},</pre>
</div>
<p>我们在启动Web API的时候,在Program.cs 代码中配置好就可以了。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">MongoDB配置</span>
builder.Services.Configure&lt;Mongosettings&gt;(builder.Configuration.GetSection("MongoSettings"));</pre>
</div>
<p>默认初始化的IMongoDBContext是一个空接口,我们可以在Web API启动的时候,指定一个具体的实现就可以了</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">添加IMongoContext实现类</span>
builder.Services.AddSingleton&lt;IMongoDBContext, <span style="color: rgba(255, 0, 0, 1)"><strong>MongoDBContext</strong></span>&gt;();</pre>
</div>
<p>对于基类接口,分页查询获取对应列表数据,是常规的处理方式,默认需要排序、分页,返回对应的数据结构,如下代码所示。</p>
<div class="cnblogs_code">
<pre>      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">/ &lt;summary&gt;</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">/ 根据条件获取列表</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">/ &lt;/summary&gt;</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">/ &lt;param name="input"&gt;分页查询条件&lt;/param&gt;</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">/ &lt;returns&gt;&lt;/returns&gt;</span>
      public virtual async Task&lt;PagedResultDto&lt;TEntity&gt;&gt;<span style="color: rgba(0, 0, 0, 1)"> GetListAsync(TGetListInput input)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> query =<span style="color: rgba(0, 0, 0, 1)"> CreateFilteredQueryAsync(input);
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> totalCount =<span style="color: rgba(0, 0, 0, 1)"> await query.CountAsync();
            
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">排序处理</span>
            query =<span style="color: rgba(0, 0, 0, 1)"> ApplySorting(query, input);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">分页处理</span>
            query =<span style="color: rgba(0, 0, 0, 1)"> ApplyPaging(query, input);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取列表</span>
            <span style="color: rgba(0, 0, 255, 1)">var</span> list =<span style="color: rgba(0, 0, 0, 1)"> await query.ToListAsync();

            </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(255, 0, 0, 1)"><strong>PagedResultDto</strong></span>&lt;TEntity&gt;<span style="color: rgba(0, 0, 0, 1)">(
               totalCount,
               list
         );
      }</span></pre>
</div>
<p>其中<strong>PagedResultDto&nbsp;</strong><em>是我们SqlSugar开发框架参照ABP框架定义一个数据结构,包含一个TotalCount数量和一个Items的对象集合。而其中&nbsp;</em>CreateFilteredQueryAsync 是定义的一个可供业务子类重写的函数,用来处理具体的查询条件。在基类BaseMongoService中只是提供一个默认的可查询对象。</p>
<div class="cnblogs_code">
<pre>      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">/ &lt;summary&gt;</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">/ 留给子类实现过滤条件的处理</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">/ &lt;/summary&gt;</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">/ &lt;returns&gt;&lt;/returns&gt;</span>
      protected virtual IMongoQueryable&lt;TEntity&gt;<span style="color: rgba(0, 0, 0, 1)"><strong><span style="color: rgba(255, 0, 0, 1)"> CreateFilteredQueryAsync</span></strong>(TGetListInput input)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> collection.AsQueryable();
      }</span></pre>
</div>
<p>例如,对于一个具体的业务对象操作类,CustomerService的定义如下所示,并且具体化查询的条件处理,如下代码所示。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">namespace SugarProject.Core.MongoDB
{
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">/ &lt;summary&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">/ 基于MongoDB数据库的应用层服务接口实现</span>
    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">/ &lt;/summary&gt;</span>
    public class CustomerService : BaseMongoService&lt;CustomerInfo, CustomerPagedDto&gt;<span style="color: rgba(0, 0, 0, 1)">, ICustomerService
    {
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">/ &lt;summary&gt;</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">/ 构造函数</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">/ &lt;/summary&gt;</span>
<span style="color: rgba(0, 0, 0, 1)">      public CustomerService()
      {
      }
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">/ &lt;summary&gt;</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">/ 自定义条件处理</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">/ &lt;/summary&gt;</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">/ &lt;param name="input"&gt;查询条件Dto&lt;/param&gt;</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">/ &lt;returns&gt;&lt;/returns&gt;</span>
      protected override IMongoQueryable&lt;CustomerInfo&gt;<span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)"><strong> CreateFilteredQueryAsync</strong></span>(CustomerPagedDto input)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> query =<span style="color: rgba(0, 0, 0, 1)"> base.CreateFilteredQueryAsync(input);

            query </span>=<span style="color: rgba(0, 0, 0, 1)"> query
                .Where(t</span>=&gt; !input.ExcludeId.IsNullOrWhiteSpace() &amp;&amp; t.Id != input.ExcludeId) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">不包含排除ID</span>
                .Where(t=&gt; !input.Name.IsNullOrWhiteSpace() &amp;&amp; t.Name.Contains(input.Name)) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如需要精确匹配则用Equals</span>                                                                                             <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">年龄区间查询</span>
                .Where(t=&gt; input.AgeStart.HasValue &amp;&amp; t.Age &gt;=<span style="color: rgba(0, 0, 0, 1)"> input.AgeStart.Value)
                .Where(t </span>=&gt; input.AgeEnd.HasValue &amp;&amp; t.Age &lt;=<span style="color: rgba(0, 0, 0, 1)"> input.AgeEnd.Value)
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">创建日期区间查询</span>
                .Where(t =&gt; input.CreateTimeStart.HasValue &amp;&amp; t.CreateTime &gt;=<span style="color: rgba(0, 0, 0, 1)"> input.CreateTimeStart.Value)
                .Where(t </span>=&gt; input.CreateTimeEnd.HasValue &amp;&amp; t.CreateTime &lt;=<span style="color: rgba(0, 0, 0, 1)"> input.CreateTimeEnd.Value)
                ;

            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> query;
      }</span></pre>
</div>
<p>这个处理方式类似于常规关系型数据库的处理方式,就是对条件的判断处理。而具体的业务对象模型,和常规框架的实体类很类似。</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 客户信息
    </span><span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 继承自BaseMongoEntity,拥有Id主键属性
    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> CustomerInfo : <span style="color: rgba(255, 0, 0, 1)"><strong>BaseMongoEntity</strong></span>
    {
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 默认构造函数(需要初始化属性的在此处理)
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> CustomerInfo()
      {
            </span><span style="color: rgba(0, 0, 255, 1)">this</span>.CreateTime =<span style="color: rgba(0, 0, 0, 1)"> System.DateTime.Now;
      }

      </span><span style="color: rgba(0, 0, 255, 1)">#region</span> Property Members

      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 姓名
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">virtual</span> <span style="color: rgba(0, 0, 255, 1)">string</span> Name { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 年龄
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">virtual</span> <span style="color: rgba(0, 0, 255, 1)">int</span> Age { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 创建人
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">virtual</span> <span style="color: rgba(0, 0, 255, 1)">string</span> Creator { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 创建时间
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">virtual</span> DateTime CreateTime { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }

      </span><span style="color: rgba(0, 0, 255, 1)">#endregion</span><span style="color: rgba(0, 0, 0, 1)">
    }</span></pre>
</div>
<p>对于插入和更新操作等常规操作,我们调用普通的Collection操作处理就可以了</p>
<div class="cnblogs_code">
<pre>      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 创建对象
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="input"&gt;</span><span style="color: rgba(0, 128, 0, 1)">实体对象</span><span style="color: rgba(128, 128, 128, 1)">&lt;/param&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;returns&gt;&lt;/returns&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">virtual</span> <span style="color: rgba(0, 0, 255, 1)">async</span><span style="color: rgba(0, 0, 0, 1)"> Task InsertAsync(TEntity input)
      {
            SetObjectIdIfEmpty(input);</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如果Id为空,设置为ObjectId的值</span>
            <span style="color: rgba(0, 0, 255, 1)">await</span><span style="color: rgba(0, 0, 0, 1)"> collection.InsertOneAsync(input);
      }

      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 更新记录
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">virtual</span> <span style="color: rgba(0, 0, 255, 1)">async</span> Task&lt;<span style="color: rgba(0, 0, 255, 1)">bool</span>&gt;<span style="color: rgba(0, 0, 0, 1)"> UpdateAsync(TEntity input)
      {
            SetObjectIdIfEmpty(input);</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如果Id为空,设置为ObjectId的值

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">await _dbSet.ReplaceOneAsync(Builders&lt;TEntity&gt;.Filter.Eq("_id", input.Id), input);

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">要修改的字段</span>
            <span style="color: rgba(0, 0, 255, 1)">var</span> list = <span style="color: rgba(0, 0, 255, 1)">new</span> List&lt;UpdateDefinition&lt;TEntity&gt;&gt;<span style="color: rgba(0, 0, 0, 1)">();
            </span><span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> item <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> input.GetType().GetProperties())
            {
                </span><span style="color: rgba(0, 0, 255, 1)">if</span> (item.Name.ToLower() == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">id</span><span style="color: rgba(128, 0, 0, 1)">"</span>) <span style="color: rgba(0, 0, 255, 1)">continue</span><span style="color: rgba(0, 0, 0, 1)">;
                list.Add(Builders</span>&lt;TEntity&gt;<span style="color: rgba(0, 0, 0, 1)">.Update.Set(item.Name, item.GetValue(input)));
            }
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> updatefilter = Builders&lt;TEntity&gt;<span style="color: rgba(0, 0, 0, 1)">.Update.Combine(list);
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> update = <span style="color: rgba(0, 0, 255, 1)">await</span> collection.UpdateOneAsync(Builders&lt;TEntity&gt;.Filter.Eq(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_id</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, input.Id), updatefilter);
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> result = update != <span style="color: rgba(0, 0, 255, 1)">null</span> &amp;&amp; update.ModifiedCount &gt; <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> result;
      }</span></pre>
</div>
<p>更新操作,有一种整个替换更新,还有一个是部分更新,它们两者是有区别的。如果对于部分字段的更新,那么操作如下所示 ,主要是利用UpdateDefinition对象来指定需要更新那些字段属性及值等信息。</p>
<div class="cnblogs_code">
<pre>      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 封装处理更新的操作(部分字段更新)
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;example&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)">var update = Builders</span><span style="color: rgba(128, 128, 128, 1)">&lt;UserInfo&gt;</span><span style="color: rgba(0, 128, 0, 1)">.Update.Set(s =&gt; s.Name, newName);
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/example&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">virtual</span> <span style="color: rgba(0, 0, 255, 1)">async</span> Task&lt;<span style="color: rgba(0, 0, 255, 1)">bool</span>&gt; UpdateAsync(<span style="color: rgba(0, 0, 255, 1)">string</span> id, <span style="color: rgba(255, 0, 0, 1)"><strong>UpdateDefinition&lt;TEntity&gt;</strong></span><span style="color: rgba(0, 0, 0, 1)"> update)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> result = <span style="color: rgba(0, 0, 255, 1)">await</span> collection.UpdateOneAsync(s =&gt; s.Id == id, update, <span style="color: rgba(0, 0, 255, 1)">new</span> UpdateOptions() { IsUpsert = <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> });
            </span><span style="color: rgba(0, 0, 255, 1)">return</span> result != <span style="color: rgba(0, 0, 255, 1)">null</span> &amp;&amp; result.ModifiedCount &gt; <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
      }</span></pre>
</div>
<p>根据MongoDB数据库的特性,我们尽量细化对数据库操作的基类接口,定义所需的接口函数即可。</p>
<p><img src="https://img2023.cnblogs.com/blog/8867/202304/8867-20230413125949442-677703866.png" alt="" width="880" height="396" loading="lazy"></p>
<p>对于Web API的控制器设计,我们在之前的随笔也有介绍,为常规授权处理的BaseApiController,为常规业务CRUD等接口处理的BusinessController,如下所示。</p>
<p><img src="https://img2023.cnblogs.com/blog/8867/202304/8867-20230413130527047-618736659.png" alt="" width="489" height="445" loading="lazy">&nbsp;</p>
<p>其中ControllerBase是.net core Web API中的标准控制器基类,我们由此派生一个LoginController用于登录授权,而BaseApiController则处理常规接口用户身份信息,而BusinessController则是对标准的增删改查等基础接口进行的封装,我们实际开发的时候,只需要开发编写类似CustomerController基类即可。</p>
<p>而对于&nbsp;MongoDB的Web API控制器,我们为了方便开发,也设计了同类型的Web API 控制器基类。</p>
<p><img src="https://img2023.cnblogs.com/blog/8867/202304/8867-20230413131218220-1899117484.png" alt="" width="446" height="440" loading="lazy"></p>
<p>其中MongoBaseController基类具有常规的CRUD的接口定义处理,只要继承它就可以了,而如果只是继承BaseApiController这需要自定义控制器接口的方法。</p>
<p>其中MongoBaseController 的基类代码部分如下所示(通过注入Service层的接口实现业务调用)。</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 基于MongoDB的业务操作接口封装的基类控制器
    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> MongoBaseController&lt;TEntity, TGetListInput&gt;<span style="color: rgba(0, 0, 0, 1)"> : BaseApiController
      </span><span style="color: rgba(0, 0, 255, 1)">where</span> TEntity : <span style="color: rgba(0, 0, 255, 1)">class</span>, IEntity&lt;<span style="color: rgba(0, 0, 255, 1)">string</span>&gt;, <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)">()
      </span><span style="color: rgba(0, 0, 255, 1)">where</span><span style="color: rgba(0, 0, 0, 1)"> TGetListInput : IPagedAndSortedResultRequest
    {
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 通用基础操作接口
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">protected</span> IBaseMongoService&lt;TEntity, TGetListInput&gt; _service { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }<br>
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 构造函数,初始化基础接口
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="service"&gt;</span><span style="color: rgba(0, 128, 0, 1)">通用基础操作接口</span><span style="color: rgba(128, 128, 128, 1)">&lt;/param&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> MongoBaseController(IBaseMongoService&lt;TEntity, TGetListInput&gt;<span style="color: rgba(0, 0, 0, 1)"> service)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">this</span>._service =<span style="color: rgba(0, 0, 0, 1)"> service;
      }      
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 获取所有记录
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 0, 0, 1)">      
      
      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">virtual</span> <span style="color: rgba(0, 0, 255, 1)">async</span> <span style="color: rgba(255, 0, 0, 1)"><strong>Task&lt;ListResultDto&lt;TEntity&gt;&gt;</strong></span><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)"><strong> GetAllAsync()</strong></span>
      {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">检查用户是否有权限,否则抛出MyDenyAccessException异常</span>
            <span style="color: rgba(0, 0, 255, 1)">base</span><span style="color: rgba(0, 0, 0, 1)">.CheckAuthorized(AuthorizeKey.ListKey);
            </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">await</span><span style="color: rgba(0, 0, 0, 1)"> _service.GetAllAsync();
      }
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 根据条件获取列表
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="input"&gt;&lt;/param&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;returns&gt;&lt;/returns&gt;</span>
<span style="color: rgba(0, 0, 0, 1)">      
      
      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">virtual</span> <span style="color: rgba(0, 0, 255, 1)">async</span> Task&lt;PagedResultDto&lt;TEntity&gt;&gt;<span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)"><strong> GetListAsync( TGetListInput input)</strong></span>
      {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">检查用户是否有权限,否则抛出MyDenyAccessException异常</span>
            <span style="color: rgba(0, 0, 255, 1)">base</span><span style="color: rgba(0, 0, 0, 1)">.CheckAuthorized(AuthorizeKey.ListKey);
            </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">await</span><span style="color: rgba(0, 0, 0, 1)"> _service.GetListAsync(input);
      }
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 根据ID获取单一对象
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="id"&gt;</span><span style="color: rgba(0, 128, 0, 1)">主键ID</span><span style="color: rgba(128, 128, 128, 1)">&lt;/param&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;returns&gt;&lt;/returns&gt;</span>
<span style="color: rgba(0, 0, 0, 1)">      
      
      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">virtual</span> <span style="color: rgba(0, 0, 255, 1)">async</span><strong><span style="color: rgba(255, 0, 0, 1)"> Task&lt;TEntity&gt; GetAsync(string</span></strong><span style="color: rgba(0, 0, 0, 1)"><strong><span style="color: rgba(255, 0, 0, 1)"> id)</span></strong>
      {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">检查用户是否有权限,否则抛出MyDenyAccessException异常</span>
            <span style="color: rgba(0, 0, 255, 1)">base</span><span style="color: rgba(0, 0, 0, 1)">.CheckAuthorized(AuthorizeKey.ViewKey);
            </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">await</span><span style="color: rgba(0, 0, 0, 1)"> _service.GetAsync(id);
      }

.................</span></pre>
</div>
<p>最后我们启动Swagger进行测试对应的接口即可,实际还可以整合在UI中进行测试处理。我们安装MongoDB数据库的管理工具后,可以在MongoDBCompass 中进行查询对应数据库的数据。</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 客户信息的控制器对象(基于MongoDB),基于BaseApiController,需要自定义接口处理
    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 0, 0, 1)">   
   
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MongoCustomerController : BaseApiController
    {
      </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> ICustomerService _service;

      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 构造函数,并注入基础接口对象
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="service"&gt;&lt;/param&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> MongoCustomerController(ICustomerService service)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">this</span>._service =<span style="color: rgba(0, 0, 0, 1)"> service;
      }

      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 获取所有记录
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 0, 0, 1)">      
      
      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">virtual</span> <span style="color: rgba(0, 0, 255, 1)">async</span> Task&lt;ListResultDto&lt;CustomerInfo&gt;&gt;<span style="color: rgba(0, 0, 0, 1)"> GetAllAsync()
      {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">检查用户是否有权限,否则抛出MyDenyAccessException异常</span>
            <span style="color: rgba(0, 0, 255, 1)">base</span><span style="color: rgba(0, 0, 0, 1)">.CheckAuthorized(AuthorizeKey.ListKey);

            </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">await</span><span style="color: rgba(0, 0, 0, 1)"> _service.GetAllAsync();
      }</span></pre>
</div>
<p><img src="https://img2023.cnblogs.com/blog/8867/202304/8867-20230413131555039-632958989.png" alt="" width="705" height="120" loading="lazy"></p>
<p>&nbsp;而如果继承自MongoBaseController&nbsp;,那么就会具有基类MongoBaseController 公开的所有控制器方法。&nbsp;</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 客户信息的控制器对象(基于MongoDB),基于MongoBaseController,具有常规CRUD操作接口
    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 0, 0, 1)">   
   
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> MongoCustomer2Controller : MongoBaseController&lt;CustomerInfo, CustomerPagedDto&gt;<span style="color: rgba(0, 0, 0, 1)">
    {
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 构造函数,并注入基础接口对象
      </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
      <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="service"&gt;&lt;/param&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">public</span> MongoCustomer2Controller(ICustomerService service) : <span style="color: rgba(0, 0, 255, 1)">base</span><span style="color: rgba(0, 0, 0, 1)">(service)
      {
      }
    }</span></pre>
</div>
<p><img src="https://img2023.cnblogs.com/blog/8867/202304/8867-20230413131703663-851254191.png" alt="" width="873" height="690" loading="lazy"></p>
<p>&nbsp;<img src="https://img2023.cnblogs.com/blog/8867/202304/8867-20230413133521526-835455075.png" alt="" width="809" height="533" loading="lazy"></p>
<p>早几年前曾经也介绍过该数据库的相关使用,随笔如下所示,有需要也可以了解下。</p>
<div class="PostList">
<div class="postTitl2">基于C#的MongoDB数据库开发应用(4)--Redis的安装及使用&nbsp;<span class="postDesc2">伍华聪 2016-01-12&nbsp;</span></div>
</div>
<div class="PostList">
<div class="postTitl2">基于C#的MongoDB数据库开发应用(3)--MongoDB数据库的C#开发之异步接口&nbsp;<span class="postDesc2">伍华聪 2016-01-12&nbsp;</span></div>
</div>
<div class="PostList">
<div class="postTitl2">基于C#的MongoDB数据库开发应用(2)--MongoDB数据库的C#开发&nbsp;<span class="postDesc2">伍华聪 2016-01-06</span></div>
</div>
<div class="PostList">
<div class="postTitl2">基于C#的MongoDB数据库开发应用(1)--MongoDB数据库的基础知识和使用&nbsp;<span class="postDesc2">伍华聪 2016-01-05</span></div>
<div class="postTitl2">&nbsp;</div>
</div>

</div>
<div id="MySignature" role="contentinfo">
    <div style="border-right-color: #cccccc; border-right-width: 1px; border-right-style: solid; padding-right: 5px; border-top-color: #cccccc; border-top-width: 1px; border-top-style: solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left-color: #cccccc; border-left-width: 1px; border-left-style: solid; width: 98%; padding-top: 4px; border-bottom-color: #cccccc; border-bottom-width: 1px; border-bottom-style: solid; background-color: #eeeeee;">
    <img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" alt>
    <span style="color: #000000"><span class="Apple-tab-span" style="white-space: pre"></span>
   专注于代码生成工具、.Net/Python 框架架构及软件开发,以及各种Vue.js的前端技术应用。著有Winform开发框架/混合式开发框架、微信开发框架、Bootstrap开发框架、ABP开发框架、SqlSugar开发框架、Python开发框架等框架产品。
   <br>  转载请注明出处:撰写人:伍华聪  http://www.iqidi.com <br>    </span></div><br><br>
来源:https://www.cnblogs.com/wuhuacong/p/17314207.html
頁: [1]
查看完整版本: 基于SqlSugar的开发框架循序渐进介绍(27)-- 基于MongoDB的数据库操作整合