C# 读写MongoDB

驱动:Official .NET driver for MongoDB

版本:2.5.0

 mongodb内部是用Bson格式存储的,与json大致类似但有区别,因此它也原生支持json串语法格式进行操作,

在C#版本驱动中就有BsonDucument类来处理json串,

所以大多驱动接口的泛型参数TDocument类型都可以用BsonDucument,即直接用BsonDucument来处理json和bson进行增删改查。

但是我不喜欢在C#语言还去写json,总觉得这样做以后比较难维护,所以尽量用C#语法本身去操作。

得益于驱动提供了BsonSerializer类,能够将C#中的大多数自定义class对象进行序列化与反序列化。

所以TDocument泛型参数不受限于BsonDucument,可以是任何自定义的类对象,

它内部可以将自定义的类对象序列化成BsonDucument,也可以反序列化,于是就可以在自定义对象层面操作mongodb了。

先简单做个封装类:

using MongoDB.Bson;
using MongoDB.Bson.IO;
using MongoDB.Bson.Serialization;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using MongoDB.Bson.Serialization.Attributes;

public class MongoDbHelper
    {
        private readonly IMongoDatabase _database;

        private MongoDbHelper(string connectionString, string databaseName)
        {
            var client = new MongoClient(connectionString);
            _database = client.GetDatabase(databaseName);
        }

        public Task Close()
        {
            return Task.CompletedTask;
        }

        public async Task EnsureIndexes<TC,TD>(IEnumerable<string> keys)
        {
            var collection = _database.GetCollection<TD>(typeof(TC).Name);
            await collection.Indexes.CreateManyAsync(keys.Select(key => new CreateIndexModel<TD>($"{{{key}:1}}")));
        }

        public Task<long> CountAsync<T>(string grainType, Expression<Func<T, bool>> whereFilter)
        {
            var collection = _database.GetCollection<T>(grainType);
            return collection.CountAsync(whereFilter == null ? FilterDefinition<T>.Empty :
                Builders<T>.Filter.Where(whereFilter));
        }

        
        public Task WriteData<T>(string collectionName, IEnumerable<T> data)
        {
            var collection = _database.GetCollection<BsonDocument>(collectionName);
            collection.InsertManyAsync(data.Select(d => d.ToBsonDocument())); //对象可以直接转Bson
            return Task.CompletedTask;
        }

        //TC用来指明数据库的Collection名,相当于sql表名;
        //TD类型用来指明文档序列化对象,相当于sql记录所对应的对象
        public Task WriteData<TC,TD>(IEnumerable<TD> data)
        {
             return WriteData<TD>(typeof(TC).Name, data);
        }

        //T类型用来指明文档序列化对象,相当于sql记录所对应的对象
        public async Task<List<T>> Query<T>(string collectionName, Expression<Func<T, bool>> whereFilter)
        {
            try
            {
                var collection = _database.GetCollection<T>(collectionName);
                var filterDefinition = whereFilter == null
                    ? FilterDefinition<T>.Empty
                    : Builders<T>.Filter.Where(whereFilter);
                var projection = Builders<T>.Projection.Exclude("_id");
                var findoptions = new FindOptions<T>() { Projection = projection };
                var cursor = await collection.FindAsync(filterDefinition, findoptions);
                return cursor.ToEnumerable().ToList();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            return null;
        }

        public Task<List<TD>> Query<TC, TD>(Expression<Func<TD, bool>> whereFilter)
        {
            return Query(typeof(TC).Name, whereFilter);
        }

        private async Task<List<TO>> AggregateQuery<TI, TO>(string collectionName, IEnumerable<IPipelineStageDefinition> pipelineStage)
        {
            try
            {
                var pipeline = new PipelineStagePipelineDefinition<TI, TO>(pipelineStage);
                var collection = _database.GetCollection<TI>(collectionName);
                var result = await collection.AggregateAsync(pipeline);
                return result.ToEnumerable().ToList();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            return null;
        }

        public Task<List<TO>> AggregateQuery<TC, TI, TO>(IEnumerable<IPipelineStageDefinition> pipelineStage)
        {
            return AggregateQuery<TI,TO>(typeof(TC).Name, pipelineStage);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TC">collection名称类</typeparam>
        /// <typeparam name="TI">输入文档类</typeparam>
        /// <typeparam name="TG">group by字段类型</typeparam>
        /// <typeparam name="TO">输出类型</typeparam>
        /// <param name="match"></param>
        /// <param name="groupby"></param>
        /// <param name="groupValue"></param>
        /// <returns></returns>
        public async Task<List<TO>> AggregateQuery<TC,TI,TG,TO>(Expression<Func<TI, bool>> match,
            Expression<Func<TI, TG>> groupby,
            Expression<Func<IGrouping<TG, TI>, TO>> groupValue)
        {
            var pipelineStageDefinitions = new IPipelineStageDefinition[]
            {
                PipelineStageDefinitionBuilder.Match(match),
                PipelineStageDefinitionBuilder.Group(
                    groupby,
                    groupValue)
            };
            return await AggregateQuery<TC, TI, TO>(pipelineStageDefinitions);
        }

        private async Task<List<T>> AggregateQuery<T>(string collectionName, IEnumerable<IPipelineStageDefinition> pipelineStage)
        {
            try
            {
                var pipeline = new PipelineStagePipelineDefinition<BsonDocument, BsonDocument>(pipelineStage);
                var collection = _database.GetCollection<BsonDocument>(collectionName);
                var result = await collection.AggregateAsync(pipeline);
                return result.ToEnumerable().Select(b => BsonSerializer.Deserialize<T>(b)).ToList();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            return null;
        }

        public Task<List<TO>> AggregateQuery<TC,TO>(IEnumerable<string> pipelineStageJson)
        {
            return AggregateQuery<TO> (typeof(TC).Name,pipelineStageJson.Select(
                json => new JsonPipelineStageDefinition<BsonDocument,BsonDocument>(json)
                    as IPipelineStageDefinition).ToList());
        }
    }

 

自定义一个类:

 

 

public class Recharge
    {
        public long UserId { get; set; }
        public ulong Amount { get; set; }
        [BsonDateTimeOptions(Kind = DateTimeKind.Local)]
        public DateTime Time { get; set; } = DateTime.Now;
    }


先打开个数据库连接:

 

//连接串和数据库名参数按自己的实际情况填
     var helper = new MongoDbHelper("XXXX","YYYY");

 

写数据:

 

        //写入多条数据
            await helper.WriteData<Recharge, Recharge>(new[]
            {
                new Recharge() {UserId = 1, Amount = 100},
                new Recharge() {UserId = 1, Amount = 200},
                new Recharge() {UserId = 2, Amount = 500},
                new Recharge() {UserId = 2, Amount = 1000},
                new Recharge() {UserId = 3, Amount = 800},
                new Recharge() {UserId = 4, Amount = 100},
            });

 

查询数据:

 

       //按id筛选
            var list1 = await helper.Query<Recharge, Recharge>(recharge=>recharge.UserId == 1);
            
            //按时间筛选
            var list2 = await helper.Query<Recharge, Recharge>(
                recharge => recharge.Time >= DateTime.MinValue &&
                            recharge.Time <= DateTime.Now);

            //按金额筛选
            var list3 = await helper.Query<Recharge, Recharge>(
                recharge => recharge.Amount >= 500);

注:开始新手的我以为查询过程是:先将bson文档反序列化成C#对象,再调用C#的lambda进行筛选。如果直接这样,效率肯定很低,相当于总是要全盘扫描。而实际上是驱动内部把lambda函数解析成了Expression表达式,再解析翻译为了原生json串查询语法,相较于原本的json语法操作,只是牺牲了点翻译时间。


统计查询:

 

       //先定义一个统计类对象
            public class RechargeStat
            {
                public long UserId { get; set; }
                public ulong Amount { get; set; }
            }

            //统计所有人的总充值
            var stats = await helper.AggregateQuery<Recharge, Recharge, long, RechargeStat>(
                recharge=>true, //直接返回true,即不筛选
                recharge=>recharge.UserId,//按UserId统计,相当于sql的group by UserId
                group =>new RechargeStat()
                {
                    UserId = group.Key,
                    Amount = (ulong)group.Sum(v=>(double)v.Amount)
                }
            );

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

操作monodb的c#封装,调用非常方便,可以继承,功能包括: 1、所有数据库操作 2、前台表格类数据获取 public List GetList(List lstColName, Document query, JqGridParam jqParam, ref int count),封装了通用的获取前台表格数据的方法,将在工程中减少大量数据库访问代码,有了这个后对前台表格类查询我们可以不用在Control里使用linq或者封装在Model里然后对前台定义视图类了,使用如下: try { JqGridParam jqParam = new JqGridParam(); jqParam.page = 1; jqParam.rows = 1000; MemberOper memOper = new MemberOper(); MongoBasicOper monOper = new MongoBasicOper(DTName.GROUP_MEMBER); int count = 0; //过滤条件 Document query = new Document(); if (!string.IsNullOrEmpty(find)) { MongoRegex reg = new MongoRegex(".*" + find + ".*"); query.Add(DColName.Name, reg); } query.Add(DColName.GroupId, g); Document[] docStatus = new Document[] { new Document(DColName.Status, RowStatus.Pass), new Document(DColName.Status, RowStatus.Admin) }; query.Add("$or", docStatus); //查询列 List lstColName = new List(); lstColName.Add(DColName.UserId); lstColName.Add(DColName.UserName); //查询数据 var lstRes = monOper.GetListEx(lstColName, query, jqParam, ref count); //转换返回值 JqGrid jg = new JqGrid(); if (count == 0) { return Json(jg.toNull(jqParam), JsonRequestBehavior.AllowGet); } var jsonData = jg.toJson(jqParam, count, lstRes, lstColName); jsonData.param = g; return Json(jsonData, JsonRequestBehavior.AllowGet); } catch (Exception e) { return Json(e.Message, JsonRequestBehavior.AllowGet); }
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值