基於官方驅動封裝mongodb

仍是一如既往先把結構圖放出來,上上個版本添加了redis的緩存,可是不知足個人需求,由於公司有項目要求是分佈式因此呢,這裏我就增長了mongoDb進行緩存分佈式,好了先看結構圖(1)。git

總的來講比較蛋疼,由於歷來沒有使用過mongoDB,從安裝,到轉爲windows服務,設置權限等等,好吧這都是題外話。redis

在寫這個MongoDB版本的時候遇到的一些問題,我先總結下:sql

1.MongoDb版本是官網最新版3.4.4,官方驅動爲2.4.3,首先個人項目是以GUID作爲主鍵,在往MongonDB中插入時遇到的是將GUID生成了MongoDB的LUUID格式產生了這樣的格式(2)而且和個人數據庫不一樣(3)固然redis也不一樣(4)。shell

a)帶着問題咱們去解決查了文檔發現原來由於bson的鍵要標識成GUID,而且格式要轉爲string,既然知道問題了就去解決找到個人GUID主鍵,以下圖(5):數據庫

在主鍵上加上 [BsonId(IdGenerator = typeof(GuidGenerator)), BsonRepresentation(BsonType.String)]這段就能夠了,看了下效果確實能夠了(6)。windows

2.可是在測試過程當中查詢的時候卻找不到,一查原來個人數據庫redis的id值都不同,這又是怎麼回事?緩存

b)原來mongoDB生成的GUID和C#生成的GUID的進制是不同的,爲了解決這個問題,Google了一下,找到了一個腳本,把這個js腳本放在mongoDB裏面執行一下,而後生成的GUID就和數據庫的同樣了。如圖(7):異步

而後生成的_id就和我數據redis的同樣了。(8)(9)async

解決完成這些問題後開始寫本身的封裝類。分佈式

但願你們多給出建議,博主也是第一次玩mongoDB,若是有好的學習資源也請推薦給博主。

第一步建立鏈接:

using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace KuRuMi.Mio.DoMain.MongoDbCache.MongoDbCommon
{
    public class MongoDbManager
    {
        private static IMongoDatabase db = null;
        private static readonly object locker = new object();
        /// <summary>
        /// 使用單列模式建立鏈接
        /// </summary>
        /// <returns></returns>
        public static IMongoDatabase CreateDb()
        {
            if (db == null)
            {
                lock (locker)
                {
                    if (db == null)
                    {
                        MongoClient Client = new MongoClient(MongoDbConfig.Host);
                        db = Client.GetDatabase(MongoDbConfig.DataBase);
                    }
                }
            }
            return db;
        }
    }
}
View Code

第二步建立DB:

using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace KuRuMi.Mio.DoMain.MongoDbCache.MongoDbCommon
{
    public class MongoDbBase
    {
        private IMongoDatabase db = null;
        public IMongoDatabase Db { get => db; }
        public MongoDbBase()
        {
            db = MongoDbManager.CreateDb();
        }
    }
}
View Code

而後呢獻上本身的封裝helper:

using KuRuMi.Mio.DoMain.MongoDbCache.MongoDbCommon;
using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace KuRuMi.Mio.DoMain.MongoDbCache.MongoDbCache
{
    /// <summary>
    /// MongoDb緩存
    /// </summary>
    public sealed class MongoDbCacheService : MongoDbBase
    {
        #region 同步
        #region 增長
        /// <summary>
        /// 保存單個對象
        /// </summary>
        /// <param name="Root"></param>
        /// <returns></returns>
        public bool AddSignleObject<TAggregateRoot>(TAggregateRoot Root)
        {
            try
            {
                var collection = Db.GetCollection<TAggregateRoot>(typeof(TAggregateRoot).Name);
                collection.InsertOne(Root);
                return true;
            }
            catch (Exception)
            {
                return false;
            }

        }
        /// <summary>
        /// 批量保存多個對象
        /// </summary>
        /// <param name="Root"></param>
        /// <returns></returns>
        public bool AddManyObject<TAggregateRoot>(List<TAggregateRoot> Root)
        {
            try
            {
                var collection = Db.GetCollection<TAggregateRoot>(typeof(TAggregateRoot).Name);
                collection.InsertMany(Root);
                return true;
            }
            catch (Exception)
            {
                return false;
            }

        }
        #endregion

        #region 刪除
        /// <summary>
        /// 刪除單個記錄
        /// </summary>
        /// <typeparam name="TAggregateRoot"></typeparam>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public int DeleteSingleIndex<TAggregateRoot>(Expression<Func<TAggregateRoot, bool>> filter)
        {
            try
            {
                var collection = Db.GetCollection<TAggregateRoot>(typeof(TAggregateRoot).Name);
                return (int)collection.DeleteOne(filter).DeletedCount;
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        #endregion

        #region 查詢
        /// <summary>
        /// 查詢單條記錄
        /// </summary>
        /// <typeparam name="TAggregateRoot"></typeparam>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public TAggregateRoot FindSingleIndex<TAggregateRoot>(Expression<Func<TAggregateRoot, bool>> filter)
        {
            try
            {
                var collection = Db.GetCollection<TAggregateRoot>(typeof(TAggregateRoot).Name);
                return collection.Find(filter).FirstOrDefault();
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        /// <summary>
        /// 查詢整個集合
        /// </summary>
        /// <typeparam name="TAggregateRoot"></typeparam>
        /// <param name="filter"></param>
        /// <returns></returns>
        public List<TAggregateRoot> FindMany<TAggregateRoot>(Expression<Func<TAggregateRoot, bool>> filter)
        {
            try
            {
                var collection = Db.GetCollection<TAggregateRoot>(typeof(TAggregateRoot).Name);
                return collection.Find(filter).ToList();
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        #endregion

        #region 更新
        /// <summary>
        /// 更新單個值
        /// </summary>
        /// <typeparam name="TAggregateRoot"></typeparam>
        /// <param name="filter"></param>
        /// <param name="field"></param>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public int UpdateSingle<TAggregateRoot>(Expression<Func<TAggregateRoot, bool>> filter, string name, string parameter)
        {
            try
            {
                var collection = Db.GetCollection<TAggregateRoot>(typeof(TAggregateRoot).Name);
                var set = Builders<TAggregateRoot>.Update.Set(name, parameter);
                return (int)collection.UpdateOne(filter, set).ModifiedCount;
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        /// <summary>
        /// 更新多個值
        /// </summary>
        /// <typeparam name="TAggregateRoot"></typeparam>
        /// <param name="filter"></param>
        /// <param name="Root"></param>
        /// <param name="property"></param>
        /// <param name="replace"></param>
        public int UpdateMany<TAggregateRoot>(Expression<Func<TAggregateRoot, bool>> filter, TAggregateRoot Root, List<string> property = null, bool replace = false)
        {
            try
            {
                var collection = Db.GetCollection<TAggregateRoot>(typeof(TAggregateRoot).Name);
                var type = Root.GetType();
                //修改集合
                var list = new List<UpdateDefinition<TAggregateRoot>>();
                foreach (var propert in type.GetProperties())
                {
                    if (propert.Name.ToLower() != "id")
                    {
                        try
                        {
                            if (property == null && property.Count < 1 || property.Any(o => o.ToLower() == propert.Name.ToLower()))
                            {
                                var replaceValue = propert.GetValue(Root);
                                if (replaceValue != null)
                                    list.Add(Builders<TAggregateRoot>.Update.Set(propert.Name, replaceValue));
                                else if (replace)
                                    list.Add(Builders<TAggregateRoot>.Update.Set(propert.Name, replaceValue));
                            }
                        }
                        catch (Exception)
                        {
                            if (property == null)
                            {
                                var replaceValue = propert.GetValue(Root);
                                if (replaceValue != null)
                                    list.Add(Builders<TAggregateRoot>.Update.Set(propert.Name, replaceValue));
                                else if (replace)
                                    list.Add(Builders<TAggregateRoot>.Update.Set(propert.Name, replaceValue));
                            }
                        }
                        
                    }
                }
                if (list.Count > 0)
                {
                    var builders = Builders<TAggregateRoot>.Update.Combine(list);
                    return (int)collection.UpdateOne(filter, builders).ModifiedCount;
                }
                return 0;
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        #endregion
        #endregion

        #region 異步
        #region 增長
        /// <summary>
        /// 異步保存單個對象
        /// </summary>
        /// <param name="Root"></param>
        /// <returns></returns>
        public bool AddSignleObjectAsync<TAggregateRoot>(TAggregateRoot Root)
        {
            try
            {
                var collection = Db.GetCollection<TAggregateRoot>(typeof(TAggregateRoot).Name);
                collection.InsertOneAsync(Root);
                return true;
            }
            catch (Exception)
            {
                return false;
            }

        }
        /// <summary>
        /// 批量保存多個對象
        /// </summary>
        /// <param name="Root"></param>
        /// <returns></returns>
        public bool AddManyObjectAsync<TAggregateRoot>(List<TAggregateRoot> Root)
        {
            try
            {
                var collection = Db.GetCollection<TAggregateRoot>(typeof(TAggregateRoot).Name);
                collection.InsertManyAsync(Root);
                return true;
            }
            catch (Exception)
            {
                return false;
            }

        }
        #endregion

        #region 刪除
        /// <summary>
        /// 異步刪除單個記錄
        /// </summary>
        /// <typeparam name="TAggregateRoot"></typeparam>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public int DeleteSingleIndexAsync<TAggregateRoot>(Expression<Func<TAggregateRoot, bool>> filter)
        {
            try
            {
                var collection = Db.GetCollection<TAggregateRoot>(typeof(TAggregateRoot).Name);
                return (int)collection.DeleteOneAsync(filter).Result.DeletedCount;
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        #endregion

        #region 查詢
        /// <summary>
        /// 異步查詢單條記錄
        /// </summary>
        /// <typeparam name="TAggregateRoot"></typeparam>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public TAggregateRoot FindSingleIndexAsync<TAggregateRoot>(Expression<Func<TAggregateRoot, bool>> filter)
        {
            try
            {
                var collection = Db.GetCollection<TAggregateRoot>(typeof(TAggregateRoot).Name);
                return collection.FindAsync(filter).Result.FirstOrDefault();
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        /// <summary>
        /// 異步查詢整個集合
        /// </summary>
        /// <typeparam name="TAggregateRoot"></typeparam>
        /// <param name="filter"></param>
        /// <returns></returns>
        public List<TAggregateRoot> FindManyAsync<TAggregateRoot>(Expression<Func<TAggregateRoot, bool>> filter)
        {
            try
            {
                var collection = Db.GetCollection<TAggregateRoot>(typeof(TAggregateRoot).Name);
                return collection.FindAsync(filter).Result.ToList();
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        #endregion

        #region 更新
        /// <summary>
        /// 異步更新單個值
        /// </summary>
        /// <typeparam name="TAggregateRoot"></typeparam>
        /// <param name="filter"></param>
        /// <param name="field"></param>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public int UpdateSingleAsync<TAggregateRoot>(Expression<Func<TAggregateRoot, bool>> filter, string name, string parameter)
        {
            try
            {
                var collection = Db.GetCollection<TAggregateRoot>(typeof(TAggregateRoot).Name);
                var set = Builders<TAggregateRoot>.Update.Set(name, parameter);
                return (int)collection.UpdateOneAsync(filter, set).Result.ModifiedCount;
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        /// <summary>
        ///異步更新多個值
        /// </summary>
        /// <typeparam name="TAggregateRoot"></typeparam>
        /// <param name="filter"></param>
        /// <param name="Root"></param>
        /// <param name="property"></param>
        /// <param name="replace"></param>
        public int UpdateManyAsync<TAggregateRoot>(Expression<Func<TAggregateRoot, bool>> filter, TAggregateRoot Root, List<string> property = null, bool replace = false)
        {
            try
            {
                var collection = Db.GetCollection<TAggregateRoot>(typeof(TAggregateRoot).Name);
                var type = Root.GetType();
                //修改集合
                var list = new List<UpdateDefinition<TAggregateRoot>>();
                foreach (var propert in type.GetProperties())
                {
                    if (propert.Name.ToLower() != "id")
                    {
                        try
                        {
                            if (property == null && property.Count < 1 || property.Any(o => o.ToLower() == propert.Name.ToLower()))
                            {
                                var replaceValue = propert.GetValue(Root);
                                if (replaceValue != null)
                                    list.Add(Builders<TAggregateRoot>.Update.Set(propert.Name, replaceValue));
                                else if (replace)
                                    list.Add(Builders<TAggregateRoot>.Update.Set(propert.Name, replaceValue));
                            }
                        }
                        catch (Exception)
                        {
                            if (property == null)
                            {
                                var replaceValue = propert.GetValue(Root);
                                if (replaceValue != null)
                                    list.Add(Builders<TAggregateRoot>.Update.Set(propert.Name, replaceValue));
                                else if (replace)
                                    list.Add(Builders<TAggregateRoot>.Update.Set(propert.Name, replaceValue));
                            }
                        }

                    }
                }
                if (list.Count > 0)
                {
                    var builders = Builders<TAggregateRoot>.Update.Combine(list);
                   return (int)collection.UpdateOneAsync(filter, builders).Result.ModifiedCount;
                }
                return 0;
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        #endregion
        #endregion
    }
}
View Code

最後是腳本文件:

function HexToBase64(hex) {
    var base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    var base64 = "";
    var group;
    for (var i = 0; i < 30; i += 6) {
        group = parseInt(hex.substr(i, 6), 16);
        base64 += base64Digits[(group >> 18) & 0x3f];
        base64 += base64Digits[(group >> 12) & 0x3f];
        base64 += base64Digits[(group >> 6) & 0x3f];
        base64 += base64Digits[group & 0x3f];
    }
    group = parseInt(hex.substr(30, 2), 16);
    base64 += base64Digits[(group >> 2) & 0x3f];
    base64 += base64Digits[(group << 4) & 0x3f];
    base64 += "==";
    return base64;
}

function Base64ToHex(base64) {
    var base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var hexDigits = "0123456789abcdef";
    var hex = "";
    for (var i = 0; i < 24;) {
        var e1 = base64Digits.indexOf(base64[i++]);
        var e2 = base64Digits.indexOf(base64[i++]);
        var e3 = base64Digits.indexOf(base64[i++]);
        var e4 = base64Digits.indexOf(base64[i++]);
        var c1 = (e1 << 2) | (e2 >> 4);
        var c2 = ((e2 & 15) << 4) | (e3 >> 2);
        var c3 = ((e3 & 3) << 6) | e4;
        hex += hexDigits[c1 >> 4];
        hex += hexDigits[c1 & 15];
        if (e3 != 64) {
            hex += hexDigits[c2 >> 4];
            hex += hexDigits[c2 & 15];
        }
        if (e4 != 64) {
            hex += hexDigits[c3 >> 4];
            hex += hexDigits[c3 & 15];
        }
    }
    return hex;
}

function UUID(uuid) {
    var hex = uuid.replace(/[{}-]/g, ""); // remove extra characters
    var base64 = HexToBase64(hex);
    return new BinData(4, base64); // new subtype 4
}

function JUUID(uuid) {
    var hex = uuid.replace(/[{}-]/g, ""); // remove extra characters
    var msb = hex.substr(0, 16);
    var lsb = hex.substr(16, 16);
    msb = msb.substr(14, 2) + msb.substr(12, 2) + msb.substr(10, 2) + msb.substr(8, 2) + msb.substr(6, 2) + msb.substr(4, 2) + msb.substr(2, 2) + msb.substr(0, 2);
    lsb = lsb.substr(14, 2) + lsb.substr(12, 2) + lsb.substr(10, 2) + lsb.substr(8, 2) + lsb.substr(6, 2) + lsb.substr(4, 2) + lsb.substr(2, 2) + lsb.substr(0, 2);
    hex = msb + lsb;
    var base64 = HexToBase64(hex);
    return new BinData(3, base64);
}

function CSUUID(uuid) {
    var hex = uuid.replace(/[{}-]/g, ""); // remove extra characters
    var a = hex.substr(6, 2) + hex.substr(4, 2) + hex.substr(2, 2) + hex.substr(0, 2);
    var b = hex.substr(10, 2) + hex.substr(8, 2);
    var c = hex.substr(14, 2) + hex.substr(12, 2);
    var d = hex.substr(16, 16);
    hex = a + b + c + d;
    var base64 = HexToBase64(hex);
    return new BinData(3, base64);
}

function PYUUID(uuid) {
    var hex = uuid.replace(/[{}-]/g, ""); // remove extra characters
    var base64 = HexToBase64(hex);
    return new BinData(3, base64);
}

BinData.prototype.toUUID = function () {
    var hex = Base64ToHex(this.base64()); // don't use BinData's hex function because it has bugs in older versions of the shell
    var uuid = hex.substr(0, 8) + '-' + hex.substr(8, 4) + '-' + hex.substr(12, 4) + '-' + hex.substr(16, 4) + '-' + hex.substr(20, 12);
    return 'UUID("' + uuid + '")';
}

BinData.prototype.toJUUID = function () {
    var hex = Base64ToHex(this.base64()); // don't use BinData's hex function because it has bugs in older versions of the shell
    var msb = hex.substr(0, 16);
    var lsb = hex.substr(16, 16);
    msb = msb.substr(14, 2) + msb.substr(12, 2) + msb.substr(10, 2) + msb.substr(8, 2) + msb.substr(6, 2) + msb.substr(4, 2) + msb.substr(2, 2) + msb.substr(0, 2);
    lsb = lsb.substr(14, 2) + lsb.substr(12, 2) + lsb.substr(10, 2) + lsb.substr(8, 2) + lsb.substr(6, 2) + lsb.substr(4, 2) + lsb.substr(2, 2) + lsb.substr(0, 2);
    hex = msb + lsb;
    var uuid = hex.substr(0, 8) + '-' + hex.substr(8, 4) + '-' + hex.substr(12, 4) + '-' + hex.substr(16, 4) + '-' + hex.substr(20, 12);
    return 'JUUID("' + uuid + '")';
}

BinData.prototype.toCSUUID = function () {
    var hex = Base64ToHex(this.base64()); // don't use BinData's hex function because it has bugs in older versions of the shell
    var a = hex.substr(6, 2) + hex.substr(4, 2) + hex.substr(2, 2) + hex.substr(0, 2);
    var b = hex.substr(10, 2) + hex.substr(8, 2);
    var c = hex.substr(14, 2) + hex.substr(12, 2);
    var d = hex.substr(16, 16);
    hex = a + b + c + d;
    var uuid = hex.substr(0, 8) + '-' + hex.substr(8, 4) + '-' + hex.substr(12, 4) + '-' + hex.substr(16, 4) + '-' + hex.substr(20, 12);
    return 'CSUUID("' + uuid + '")';
}

BinData.prototype.toPYUUID = function () {
    var hex = Base64ToHex(this.base64()); // don't use BinData's hex function because it has bugs
    var uuid = hex.substr(0, 8) + '-' + hex.substr(8, 4) + '-' + hex.substr(12, 4) + '-' + hex.substr(16, 4) + '-' + hex.substr(20, 12);
    return 'PYUUID("' + uuid + '")';
}


BinData.prototype.toHexUUID = function () {
    var hex = Base64ToHex(this.base64()); // don't use BinData's hex function because it has bugs
    var uuid = hex.substr(0, 8) + '-' + hex.substr(8, 4) + '-' + hex.substr(12, 4) + '-' + hex.substr(16, 4) + '-' + hex.substr(20, 12);
    return 'HexData(' + this.subtype() + ', "' + uuid + '")';
}
View Code

倉儲層的調用:

using KuRuMi.Mio.DoMain.Model.Model;
using KuRuMi.Mio.DoMain.Model.Repositories;
using KuRuMi.Mio.DoMain.Repository.EFRepository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace KuRuMi.Mio.DoMain.Repository.ModelRepository
{
    public class UserRepositoryImpl : RepositoryImpl<User>, IUserRepository
    {
        public KurumiMioDbContext context => lazy.Context as KurumiMioDbContext;
        /// <summary>
        /// 登陸
        /// </summary>
        /// <param name="Email"></param>
        /// <param name="PassWord"></param>
        /// <returns></returns>
        public string CheckUser(string Email, string PassWord)
        {
            try
            {
                User entity = null;
                //MongoDb取
                entity = Mongo.FindSingleIndex<User>(a => a.Email == Email);
                if (entity == null)
                {
                    //redis取
                    entity = Redis.RedisString.Value.StringGet<User>(Email);
                }
                if (entity == null)
                {
                    //數據庫取
                    string sql = "select Id,UserName,Password,email from [User] as a where a.Email ='{0}' and  a.PassWord ='{1}'";
                    string select = string.Format(sql, Email, PassWord);
                    entity = context.user.SqlQuery(select).FirstOrDefault();
                }
                return entity.UserName;
            }
            catch (Exception e)
            {
                return "";
            }
        }

        /// <summary>
        /// 保存
        /// </summary>
        /// <param name="aggregateRoot"></param>
        public async override void Add(User aggregateRoot)
        {
            base.Add(aggregateRoot);
            await Redis.RedisString.Value.StringSetAsync(aggregateRoot.Email, aggregateRoot);//保存一份到redis
            Mongo.AddSignleObjectAsync(aggregateRoot);//保存一份到mongoDb
        }

        /// <summary>
        /// 註冊
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        public User GetAll(User info)
        {
            string sql = "select Id,UserName,Password,email from [User] as a where a.UserName ='{0}' and email ='{1}'";
            string select = string.Format(sql, info.UserName, info.Email);
            return context.user.SqlQuery(select).FirstOrDefault();
        }
    }
}
View Code

 圖1:

圖2:

圖3:

圖4:

圖5:

 

圖6:

圖7:

圖8:

圖9:

相關文章
相關標籤/搜索