MongoDB 系列(一) C# 类似EF语法简单封装

之前写过一篇关于MongoDB的封装 发现太过繁琐 于是打算从新写一篇简易版

1:关于MongoDB的安装请自行百度,进行权限认证的时候有一个小坑,3.0之后授权认证方式默认的SCRAM-SHA-1模式,

需要首先命令创建一个用户,然后Drop掉这个用户,然后修改system.version里的authScheam为3,在没有创建用户的情况下

authScheam的值貌似是查询不到的。

修改成3后,授权验证方式就变成了MONGODB-CR

 2:建立一个聚合根和实体

 public interface ICore
    {
        string Id { set; get; }
    }

    /// <summary>
    /// 聚合根
    /// </summary>
    public interface IAggregateRoot
    {
         string Id { set; get; }
    }

    /// <summary>
    /// 实体
    /// </summary>
    public abstract class Core : ICore
    {
        public string Id { set; get; } = Guid.NewGuid().ToString();
    }

3:建立实体

/// <summary>
    /// 用户
    /// </summary>
    public class User : Core, IAggregateRoot
    {
        /// <summary>
        /// 名字
        /// </summary>
        public string Name { set; get; }

        /// <summary>
        /// 身份证
        /// </summary>
        public string Cardcertificate { set; get; }

        /// <summary>
        /// 性别
        /// </summary>
        public Gender Gender { set; get; } = Gender.Boy;

        /// <summary>
        /// 用户的房屋信息
        /// </summary>
        public List<House> Houses { set; get; } = new List<House>();
    }

    public class House : Core
    {
        public string Adress { set; get; }
    }

    public enum Gender
    {
        Boy = 0,
        Gril = 1
    }

4:建立一个接口Context似于EF的DBContext

    public interface IMongoDBContext
    {

        /// <summary>
        /// 具体的表连接器
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <returns></returns>
       IMongoCollection<K> DbSet<K>() where K : IAggregateRoot;

    }

添加一个接口的实现

Client 表示的是Mongodb客户端驱动链接 类似于ADO里的SqlConnection

DataBase 表示的是具体的数据库

DbSet 指定具体的表

3:建立一个具体的DBContext

BasicContext  类似于EF里面大家直接链接具体库的DBContext

Users User表的映射

4:建立一个MongoDB访问的扩展类

    public static class MongodbExpansion
    {
        /// <summary>
        /// 单个对象添加
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="collection"></param>
        /// <param name="entity"></param>
        public static void Add<T>(this IMongoCollection<T> collection, T entity) where T : IAggregateRoot
            => collection.InsertOne(entity);

        /// <summary>
        /// 集合添加
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="collection"></param>
        /// <param name="entitys"></param>
        public static void AddRange<T>(this IMongoCollection<T> collection, List<T> entitys) where T : IAggregateRoot
            => collection.InsertMany(entitys);

        /// <summary>
        /// entity mongodb需要更新的实体 properts需要更新的集合属性,大小写不限 默认更新整个对象 replace 默认空属性不修改
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="collection"></param>
        /// <param name="entity">mongodb需要更新的实体</param>
        /// <param name="properts">需要更新的集合属性,大小写不限 默认更新整个对象 </param>
        /// <param name="replace">默认对象属性为空时不替换当前值</param>
        public static void Update<T>(this IMongoCollection<T> collection, T entity, List<string> properts = null, bool replace = false) where T : IAggregateRoot
        {
            if (entity == null)
                throw new NullReferenceException();

            var type = entity.GetType();
            ///修改的属性集合
            var list = new List<UpdateDefinition<T>>();

            foreach (var propert in type.GetProperties())
            {
                if (propert.Name.ToLower() != "id")
                {
                    if (properts == null || properts.Count < 1 || properts.Any(o => o.ToLower() == propert.Name.ToLower()))
                    {
                        var replaceValue = propert.GetValue(entity);
                        if (replaceValue != null)
                        {
                            list.Add(Builders<T>.Update.Set(propert.Name, replaceValue));
                        }
                        else if (replace)
                            list.Add(Builders<T>.Update.Set(propert.Name, replaceValue));
                    }
                }
            }
            #region 有可修改的属性
            if (list.Count > 0)
            {
                ///合并多个修改//new List<UpdateDefinition<T>>() { Builders<T>.Update.Set("Name", "111") }
                var builders = Builders<T>.Update.Combine(list);
                ///执行提交修改
                collection.UpdateOne(o => o.Id == entity.Id, builders);
            }
            #endregion

        }

        /// <summary>
        /// 移除根据ID
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="collection"></param>
        /// <param name="entity"></param>
        public static void Remove<T>(this IMongoCollection<T> collection, T entity) where T : IAggregateRoot
        => collection.DeleteOne(o => o.Id == entity.Id);

        /// <summary>
        /// 移除表达式
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="collection"></param>
        /// <param name="expression"></param>
        public static void Remove<T>(this IMongoCollection<T> collection, Expression<Func<T, bool>> expression) where T : IAggregateRoot
        => collection.DeleteOne(expression);

        public static IFindFluent<T, T> Where<T>(this IMongoCollection<T> collection, Expression<Func<T, bool>> expression)
        => expression == null ? collection.Find(Builders<T>.Filter.Empty) : collection.Find(expression);

        /// <summary>
        /// MongoDB里面是没有实现IQueryable的 所以想要使用习惯的SELECT我们只能自己封装一下
        /// </summary>
        /// <typeparam name="TDocument"></typeparam>
        /// <typeparam name="TProjection"></typeparam>
        /// <typeparam name="TNewProjection">返回新的数据类型</typeparam>
        /// <param name="IQueryable"></param>
        /// <param name="projection"></param>
        /// <returns></returns>
        public static IFindFluent<TDocument, TNewProjection> Select<TDocument, TProjection, TNewProjection>(this IFindFluent<TDocument, TProjection> IQueryable, Expression<Func<TDocument, TNewProjection>> projection)
        => IQueryable.Project(projection);

        /// <summary>
        /// 获得筛选后的首个元素
        /// </summary>
        /// <typeparam name="TDocument"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="IQueryable"></param>
        /// <returns></returns>
        public static T FirstOrDefault<TDocument, T>(this IFindFluent<TDocument, T> IQueryable)
         => IQueryable.First();

        /// <summary>
        /// 直接支持表达式树后的首个满足对象
        /// </summary>
        /// <typeparam name="TDocument"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="collection"></param>
        /// <param name="expression"></param>
        /// <returns></returns>
        public static T FirstOrDefault<TDocument, T>(this IMongoCollection<T> collection, Expression<Func<T, bool>> expression = null)
        => expression == null ? collection.Find(Builders<T>.Filter.Empty).First() : collection.Find(expression).First();
    }

5:建立仓储

6:仓储的实现  是不是看起来有点EF的感觉? ~0~

7:建立Service接口

8 领域服务的实现

9:单元测试用例

 BasicContext Context = new BasicContext();
            Context.Users.Add(new Entity.User()
            {
                Name = "小七子",
                Cardcertificate = "123456789",
                Gender = Entity.Gender.Boy,
                Houses = new System.Collections.Generic.List<Entity.House>() { new Entity.House() { Adress = "中关村110号双拼别墅" } }
            });

            Context.Users.Where(o => o.Cardcertificate == "110").ToList();

            Context.Users.Update(new Entity.User() { });

            Context.Users.Remove(new Entity.User() { });

            Context.Users.Where().Select(o => o.Name).ToList();
            Console.ReadKey();

也可以像EF类似操作 

时间: 2024-08-10 13:14:17

MongoDB 系列(一) C# 类似EF语法简单封装的相关文章

MongoDB系列教程(八):GridFS存储详解

MongoDB系列教程(八):GridFS存储详解 GridFS简介 mongoDB的文档以BSON格式存储,支持二进制的数据类型,当我们把二进制格式的数据直接保存到mongoDB的文档中.但是当文件太大时,例如图片和视频等文件,每个文档的长度是有限的,于是mongoDb会提供了一种处理大文件的规范--GridFS. GridFS实现原理 在GridFS数据库中,默认使用fs.chunks 和fs.files来存储文件,其中fs.files集合存放文件的信息,fs.chunks存放文件的数据,一

MongoDB系列---用户及权限管理02

MongoDB-——Privilege 学习大纲: 1.用户权限管理 2.用户操作 知识回顾:  本系列上一篇博文我们讲述了如何搭建环境以及配置我们的MongoDB,通过搭建环境后我们又学习了如何通过简单的命令和配置来启动关闭我们的MongoDB. 一 用户及权限管理 前言: MongoDB 作为时下最为热门的数据库,那么其安全验证也是必不可少的,否则一个没有验证的数据库暴露出去,任何人可随意操作,这将是非常危险的.我们可以通过使用为MongoDB 创建用户的方式来降低风险 1 MongoDB用

LINQ to Objects系列(2)两种查询语法介绍

LINQ为我们提供了两种查询语法,分别是查询表达式和查询方法语法.这篇文章分为以下几个方面进行总结. 1,一个包含两种查询语法的简单示例 2,查询表达式的结构 3,查询方法相关的运算符 一个包含两种查询语法的简单示例 一个LINQ查询既可以使用查询表达式实现,也可以用查询方法实现,还可以同时组合两种查询.下面是一个简单的示例,代码如下. namespace LINQDemo3 { class Program { static void Main(string[] args) { int[] nu

详解C# 网络编程系列:实现类似QQ的即时通信程序

引言: 前面专题中介绍了UDP.TCP和P2P编程,并且通过一些小的示例来让大家更好的理解它们的工作原理以及怎样.Net类库去实现它们的.为了让大家更好的理解我们平常中常见的软件QQ的工作原理,所以在本专题中将利用前面专题介绍的知识来实现一个类似QQ的聊天程序.  一.即时通信系统 在我们的生活中经常使用即时通信的软件,我们经常接触到的有:QQ.阿里旺旺.MSN等等.这些都是属于即时通信(Instant Messenger,IM)软件,IM是指所有能够即时发送和接收互联网消息的软件. 在前面专题

mongodb系列之-治理mongodb-&gt;db.currentOp()

mongodb系列之-管理mongodb->db.currentOp() 管理mongodb->db.currentOp(), 绝对是原创... 今天公司的dba在内部分享了针对mysql上具体的每个crud语句操作如何进行控制管理(利用的inntop工具),挺好的.这里,我也献丑下,在mongodb中如何管理具体的每个crud操作(比如某个查询语句慢,太占资源,直接可以将其kill掉,这貌似很暴力哈,不过没关系,有时候不得已而为之...不过mongodb中可不是用第三方的工具哦,而是自家实现

【玩转微信公众平台之七】 PHP语法简单介绍

经过多篇的努力,我们终于成为了微信公众平台的开发者.但是别高兴的太早,就跟修真小说一样:修炼多年武破虚空,飞升到仙界后本以为成为了天仙即可跳出三界外,不在五行中.可实际到了仙界才发现,成仙只是修行的第一步......没错,成为开发者也才只是第一步,因为现在你的微信公众平台还没有任何功能,说难听点就是小白,说好听点就是白马王子,说可爱点就是小白白,说黄色点就是洗白白,说...----------------要想在微信公众平台添加功能,那就需要写代码:既然说到写代码,那么肯定是要用php(如果用AS

css基本语法简单介绍

css基本语法简单介绍:本章节介绍一下css的基本语法,比较适合于初学者阅读,对于稍有经验的人员来说,几乎没有太多帮助,可以略过.使用css的方式主要以下三种: 1.行内样式 2.内嵌样式 3.外联样式 当然可能不同的教材中的名称有所不同,不过实质都是一样的,不必太过纠结.下面分别介绍一下上面三种方式的使用.一.行内样式:所谓的行内样式就是通过标签的style属性,将css代码写在标签之内,代码如下: <div style="color:blue">softwhy.com&

Smali语法简单介绍

Smali语言其实就是Davlik的寄存器语言: Smali语言就是android的应用程序.apk通过apktool反编译出来的都有一个smali文件夹,里面都是以.smali结尾的文件,文件的展示语言. Smali语法简单介绍如下: Davlik字节码中,寄存器都是32位的,能够支持任何类型,64位类型(Long/Double)用2个寄存器表示: Dalvik字节码有两种类型:原始类型:引用类型(包括对象和数组)   原始类型:v   void  只能用于返回值类型 Z   boolean

【转】Struts1.x系列教程(2):简单的数据验证

转载地址:http://www.blogjava.net/nokiaguy/archive/2009/01/archive/2009/01/13/251197.html 简单验证从本质上说就是在服务端来验证客户端提交的form中的数据.这种验证只是对form中的数据规则进行检查,如必须输入用户ID,价格不能小于0或是对email格式的验证.在这个验证过程中,并不需要访问数据库.因此,简单验证需要在用户提交form后,并且在服务器处理form中的数据之前进行. 在进行完简单验证后,如果form中的