之前寫過一篇關於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();