zoukankan      html  css  js  c++  java
  • 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 指定具体的表

    MongoCredential 认证授权的加密方式

    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();
        }
    Builders<T>.Update.Combine 方法是将多个UpdateDefinition<T>修改设置合并成一个builder对象执行

    IFindFluent 所返回的都是MongoDB执行的命令

    MongoDB客户端驱动也是支持异步操作的我这里就没有写了 有兴趣的可以自己研究下

    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();

     

  • 相关阅读:
    算法学习笔记: 珂朵莉树
    算法学习笔记:2SAT
    0x62 图论最小生成树
    Codeforces Round #632 (Div. 2) C. Eugene and an array(尺取法/前缀和)
    BZOJ1912 异象石(LCA/DFS序/set)
    (六1)Firefox插件安装
    (六2)八种定位方式为了查找元素
    (六3)从查找元素到操作元素
    【OSI】网络协议模型
    读《Wireshark网络分析就这么简单》读书笔记
  • 原文地址:https://www.cnblogs.com/hfdel/p/7208902.html
Copyright © 2011-2022 走看看