MongoDB数据仓储
本篇是作为另一篇随笔的一部分‘搭建一个Web API项目’
MogonDB官网:https://www.mongodb.org/
安装过程参考园友的分享http://www.cnblogs.com/lzrabbit/p/3682510.html
cmd client:
C:\Users\Administrator>D:
D:\> cd D:\MongoDB\Server\3.2\bin
D:\MongoDB\Server\3.2\bin>mongo 127.0.0.1:27017
>use zheyibu
>db.SEOStudent.find()
一、项目Frozen.MongoObjects
1 /// <summary> 2 /// MongoDB支持的实体,必须要有Id 3 /// </summary> 4 public interface IEntity 5 { 6 [BsonId] 7 int Id { get; set; } 8 }
1 /// <summary> 2 /// 3 /// </summary> 4 public class SEOStudent : IEntity 5 { 6 /// <summary> 7 /// 8 /// </summary> 9 public int Id { get; set; } 10 11 public string Name { get; set; } 12 13 }
二、项目Frozen.MongoCommon
(这部分的代码都是从园子里拷下来的,望大神们莫怪!本文不用于任何商业用途!)
IMongoDBRepositoryContextSettings
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using MongoDB.Driver; 2 3 namespace Frozen.MongoCommon 4 { 5 /// <summary> 6 /// Represents that the implemented classes are MongoDB repository context settings. 7 /// </summary> 8 public interface IMongoDBRepositoryContextSettings 9 { 10 /// <summary> 11 /// Gets the database name. 12 /// </summary> 13 string DatabaseName { get; } 14 /// <summary> 15 /// Gets the instance of <see cref="MongoServerSettings"/> class which represents the 16 /// settings for MongoDB server. 17 /// </summary> 18 MongoClientSettings ClientSettings { get; } 19 /// <summary> 20 /// Gets the instance of <see cref="MongoDatabaseSettings"/> class which represents the 21 /// settings for MongoDB database. 22 /// </summary> 23 /// <param name="server">The MongoDB server instance.</param> 24 /// <returns>The instance of <see cref="MongoDatabaseSettings"/> class.</returns> 25 MongoDatabaseSettings GetDatabaseSettings(MongoClient client); 26 27 } 28 }
MongoDBRepositoryContextSettings
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using MongoDB.Driver; 2 using System; 3 using System.Configuration; 4 5 namespace Frozen.MongoCommon 6 { 7 /// <summary> 8 /// 表示基于MongoDB实现的仓储上下文的配置信息。 9 /// </summary> 10 /// <remarks> 11 /// 如果您的MongoDB配置不是默认的,您可以在此处修改MongoDB的配置信息,比如 12 /// 可以在ServerSettings里指定MongoDB的端口号等。 13 /// </remarks> 14 public class MongoDBRepositoryContextSettings : IMongoDBRepositoryContextSettings 15 { 16 private readonly string serverStr = "192.168.8.119"; 17 private readonly int port = 2222; 18 private readonly string dbName = "zheyibu"; 19 20 public MongoDBRepositoryContextSettings() 21 { 22 if(ConfigurationManager.AppSettings["MongoDBServer"]!=null) 23 { 24 serverStr = ConfigurationManager.AppSettings["MongoDBServer"]; 25 } 26 if (ConfigurationManager.AppSettings["MongoDBServerPort"] != null) 27 { 28 port = Int32.Parse(ConfigurationManager.AppSettings["MongoDBServerPort"]); 29 } 30 if (ConfigurationManager.AppSettings["MongoDBDbName"] != null) 31 { 32 dbName = ConfigurationManager.AppSettings["MongoDBDbName"]; 33 } 34 } 35 36 #region IMongoDBRepositoryContextSettings Members 37 /// <summary> 38 /// 获取数据库名称。 39 /// </summary> 40 public string DatabaseName 41 { 42 get { return dbName; } 43 } 44 /// <summary> 45 /// 获取MongoDB的服务器配置信息。 46 /// </summary> 47 public MongoClientSettings ClientSettings 48 { 49 get 50 { 51 var settings = new MongoClientSettings(); 52 settings.Server = new MongoServerAddress(serverStr, port); 53 settings.WriteConcern = WriteConcern.Acknowledged; 54 return settings; 55 } 56 } 57 /// <summary> 58 /// 获取数据库配置信息。 59 /// </summary> 60 /// <param name="server">需要配置的数据库实例。</param> 61 /// <returns>数据库配置信息。</returns> 62 public MongoDatabaseSettings GetDatabaseSettings(MongoClient client) 63 { 64 // 您无需做过多的更改:此处仅返回新建的MongoDatabaseSettings实例即可。 65 return new MongoDatabaseSettings(); 66 } 67 68 #endregion 69 } 70 }
IMongoDBRepositoryContext
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using Frozen.MongoObjects; 2 using MongoDB.Driver; 3 using System; 4 5 namespace Frozen.MongoCommon 6 { 7 /// <summary> 8 /// Mongo DB Context 9 /// </summary> 10 public interface IMongoDBRepositoryContext 11 { 12 /// <summary> 13 /// Gets a <see cref="IMongoDBRepositoryContextSettings"/> instance which contains the settings 14 /// information used by current context. 15 /// </summary> 16 IMongoDBRepositoryContextSettings Settings { get; } 17 /// <summary> 18 /// Gets the <see cref="MongoCollection"/> instance by the given <see cref="Type"/>. 19 /// </summary> 20 /// <param name="type">The <see cref="Type"/> object.</param> 21 /// <returns>The <see cref="MongoCollection"/> instance.</returns> 22 IMongoCollection<T> GetCollection<T>() where T : IEntity; 23 24 /// <summary> 25 /// 从MongoDB中清除所有类型为T的对象 26 /// </summary> 27 /// <typeparam name="T"></typeparam> 28 void ClearSequence<T>(); 29 30 /// <summary> 31 /// 获取类型T的对象的下一个序列 32 /// </summary> 33 /// <typeparam name="T"></typeparam> 34 /// <returns></returns> 35 int getNextSequence<T>(); 36 } 37 }
MongoDBRepositoryContext
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using MongoDB.Bson.Serialization.Conventions; 2 using MongoDB.Driver; 3 using System; 4 using System.Collections.Generic; 5 using System.Linq; 6 using System.Reflection; 7 using System.Text; 8 using System.Threading.Tasks; 9 using MongoDB.Driver.Linq; 10 using System.Threading; 11 using Frozen.MongoObjects; 12 13 namespace Frozen.MongoCommon 14 { 15 /// <summary> 16 /// Represents the MongoDB repository context. 17 /// </summary> 18 public class MongoDBRepositoryContext : IMongoDBRepositoryContext 19 { 20 private readonly IMongoDBRepositoryContextSettings settings; 21 private readonly MongoClient client; 22 private readonly IMongoDatabase db; 23 24 /// <summary> 25 /// 构造,初始化MongoClient 26 /// </summary> 27 /// <param name="settings"></param> 28 public MongoDBRepositoryContext(IMongoDBRepositoryContextSettings settings) 29 { 30 this.settings = settings; 31 client = new MongoClient(settings.ClientSettings); 32 db = client.GetDatabase(settings.DatabaseName); 33 } 34 35 /// <summary> 36 /// Mongo 设置 37 /// </summary> 38 public IMongoDBRepositoryContextSettings Settings 39 { 40 get 41 { 42 return settings; 43 } 44 } 45 46 /// <summary> 47 /// 获取一个集合 48 /// </summary> 49 /// <typeparam name="T"></typeparam> 50 /// <returns></returns> 51 public IMongoCollection<T> GetCollection<T>() where T : IEntity 52 { 53 return db.GetCollection<T>(typeof(T).Name); 54 } 55 56 /// <summary> 57 /// 获取Id 58 /// </summary> 59 /// <typeparam name="T"></typeparam> 60 /// <returns>序列ID</returns> 61 public int getNextSequence<T>() 62 { 63 //此处代码需要优化,应该一个API方法就可以搞定 64 var collection = db.GetCollection<Counter>("counter"); 65 66 string name = typeof(T).Name; 67 var filter = Builders<Counter>.Filter.Where(t => t.id == name); 68 var last = collection.Find(filter).FirstOrDefaultAsync().Result; 69 if (last == null) 70 { 71 collection.InsertOneAsync(new Counter() { id = name, seq = 0 }); 72 } 73 74 var def = Builders<Counter>.Update.Inc(t => t.seq, 1); 75 collection.FindOneAndUpdateAsync(filter, def).Wait(); 76 return collection.Find(filter).FirstOrDefaultAsync().Result.seq; 77 78 } 79 80 /// <summary> 81 /// 清除序列 82 /// </summary> 83 /// <typeparam name="T"></typeparam> 84 public void ClearSequence<T>() 85 { 86 var collection = db.GetCollection<Counter>("counter"); 87 88 string name = typeof(T).Name; 89 var filter = Builders<Counter>.Filter.Where(t => t.id == name); 90 var def = Builders<Counter>.Update.Set(t => t.seq, 0); 91 collection.FindOneAndUpdateAsync(filter,def).Wait(); 92 } 93 } 94 95 /// <summary> 96 /// 序列 97 /// </summary> 98 public class Counter 99 { 100 /// <summary> 101 /// 类型的Id 102 /// </summary> 103 public string id { get; set; } 104 105 /// <summary> 106 /// 当前的序列 107 /// </summary> 108 public int seq { get; set; } 109 } 110 }
MongoDBRepository
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq.Expressions; 4 using MongoDB.Driver; 5 using Frozen.MongoObjects; 6 7 namespace Frozen.MongoCommon 8 { 9 /// <summary> 10 /// Represents the MongoDB repository. 11 /// </summary> 12 /// <typeparam name="T">实现了IEntity的实体类</typeparam> 13 public class MongoDBRepository<T> where T : class, IEntity 14 { 15 #region Private Fields 16 17 private readonly IMongoDBRepositoryContext mongoDBRepositoryContext; 18 private IMongoCollection<T> collection; 19 20 #endregion 21 22 /// <summary> 23 /// 构造 24 /// </summary> 25 /// <param name="context"></param> 26 public MongoDBRepository(IMongoDBRepositoryContext context) 27 { 28 mongoDBRepositoryContext = context; 29 collection = mongoDBRepositoryContext.GetCollection<T>(); 30 } 31 32 /// <summary> 33 /// MongoBD Context,一个集合 34 /// </summary> 35 protected IMongoCollection<T> DataContext 36 { 37 get { return collection ?? (collection = mongoDBRepositoryContext.GetCollection<T>()); } 38 } 39 40 /// <summary> 41 /// 添加类型实例到Mongo 42 /// </summary> 43 /// <param name="entity"></param> 44 public void Add(T entity) 45 { 46 if (entity.Id == 0) 47 { 48 entity.Id = mongoDBRepositoryContext.getNextSequence<T>(); 49 } 50 collection.InsertOneAsync(entity).Wait(); 51 } 52 53 /// <summary> 54 /// 添加集合到Mongo 55 /// </summary> 56 /// <param name="entities"></param> 57 public void AddAll(IEnumerable<T> entities) 58 { 59 foreach (var it in entities) 60 { 61 if (it.Id == 0) 62 { 63 it.Id = mongoDBRepositoryContext.getNextSequence<T>(); 64 } 65 } 66 collection.InsertManyAsync(entities).Wait(); 67 } 68 69 /// <summary> 70 /// 更新实例 71 /// </summary> 72 /// <param name="entity"></param> 73 public void Update(T entity) 74 { 75 var filter = Builders<T>.Filter.Where(t => t.Id == entity.Id); 76 collection.ReplaceOneAsync(filter, entity).Wait(); 77 } 78 79 /// <summary> 80 /// 更新一组实例 81 /// </summary> 82 /// <param name="entities"></param> 83 public void Update(IEnumerable<T> entities) 84 { 85 foreach (var it in entities) 86 { 87 Update(it); 88 } 89 } 90 91 /// <summary> 92 /// 更新或添加一组实例 93 /// </summary> 94 /// <param name="entities"></param> 95 public void UpdateOrAddAll(IEnumerable<T> entities) 96 { 97 var list2 = new List<T>(); //will be add 98 foreach (var i in entities) 99 { 100 if (GetById(i.Id) != null) 101 { 102 Update(i); 103 } 104 else 105 { 106 list2.Add(i); 107 } 108 } 109 if (list2.Count > 0) 110 { 111 AddAll(list2); 112 } 113 } 114 115 /// <summary> 116 /// 删除实例 117 /// </summary> 118 /// <param name="entity"></param> 119 public void Delete(T entity) 120 { 121 var filter = Builders<T>.Filter.Where(t => t.Id == entity.Id); 122 collection.DeleteOneAsync(filter).Wait(); 123 } 124 125 /// <summary> 126 /// 按条件删除 127 /// </summary> 128 /// <param name="where"></param> 129 public void Delete(Expression<Func<T, bool>> where) 130 { 131 collection.DeleteOneAsync(where).Wait(); 132 } 133 134 /// <summary> 135 /// 删除一组实例 136 /// </summary> 137 /// <param name="entities"></param> 138 public void DeleteAll(IEnumerable<T> entities) 139 { 140 var filter = Builders<T>.Filter.Where(t => t.Id > 0); 141 collection.DeleteManyAsync(filter).Wait(); 142 } 143 144 /// <summary> 145 /// 按Id 范围删除 146 /// </summary> 147 /// <param name="MinId"></param> 148 /// <param name="MaxId"></param> 149 public void DeleteMany(int MinId, int MaxId) 150 { 151 var filter = Builders<T>.Filter.Where(t => t.Id >= MinId && t.Id <= MaxId); 152 collection.DeleteManyAsync(filter).Wait(); 153 } 154 155 /// <summary> 156 /// 清除所以 157 /// </summary> 158 public void Clear() 159 { 160 var filter = Builders<T>.Filter.Where(t => t.Id > 0); 161 collection.DeleteManyAsync(filter).Wait(); 162 mongoDBRepositoryContext.ClearSequence<T>(); 163 } 164 165 /// <summary> 166 /// 按id查询 167 /// </summary> 168 /// <param name="Id"></param> 169 /// <returns></returns> 170 public T GetById(long Id) 171 { 172 return collection.Find(t => t.Id == Id).FirstOrDefaultAsync().Result; 173 } 174 175 /// <summary> 176 /// 按id查询 177 /// </summary> 178 /// <param name="Id"></param> 179 /// <returns></returns> 180 public T GetById(string Id) 181 { 182 var entityId = 0; 183 int.TryParse(Id, out entityId); 184 return collection.Find(t => t.Id == entityId).FirstOrDefaultAsync().Result; 185 } 186 187 /// <summary> 188 /// 按条件查询 189 /// </summary> 190 /// <param name="where"></param> 191 /// <returns></returns> 192 public T Get(Expression<Func<T, bool>> where) 193 { 194 return collection.Find(where).FirstOrDefaultAsync().Result; 195 } 196 197 /// <summary> 198 /// 获取所有 199 /// </summary> 200 /// <returns></returns> 201 public IEnumerable<T> GetAll() 202 { 203 return collection.Find(t => t.Id > 0).ToListAsync().Result; 204 } 205 206 /// <summary> 207 /// 按条件获取 208 /// </summary> 209 /// <param name="where"></param> 210 /// <returns></returns> 211 public IEnumerable<T> GetMany(Expression<Func<T, bool>> where) 212 { 213 return collection.Find(where).ToListAsync().Result; 214 } 215 216 /// <summary> 217 /// 获取所有 218 /// </summary> 219 /// <returns></returns> 220 public IEnumerable<T> GetAllLazy() 221 { 222 return collection.Find(t => t.Id > 0).ToListAsync().Result; 223 } 224 225 } 226 }
三、项目Frozen.MongoRepositories
ISEOStudentMongoRepo
using Frozen.Common.Interface; using Frozen.MongoObjects; namespace Frozen.MongoRepositories { public interface ISEOStudentMongoRepo : IRepository<SEOStudent> { } }
SEOStudentMongoRepo
1 using Frozen.MongoCommon; 2 using Frozen.MongoObjects; 3 4 namespace Frozen.MongoRepositories.Implementation 5 { 6 public class SEOStudentMongoRepo : MongoDBRepository<SEOStudent>, ISEOStudentMongoRepo 7 { 8 public SEOStudentMongoRepo(IMongoDBRepositoryContext context) 9 : base(context) 10 { 11 } 12 13 } 14 }
其中接口IRepository的定义:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Linq.Expressions; 5 using System.Text; 6 using System.Threading.Tasks; 7 8 namespace Frozen.Common.Interface 9 { 10 public interface IRepository<T> where T : class 11 { 12 void Add(T entity); 13 void AddAll(IEnumerable<T> entities); 14 void Update(T entity); 15 void Update(IEnumerable<T> entities); 16 void Delete(T entity); 17 void Delete(Expression<Func<T, bool>> where); 18 void DeleteAll(IEnumerable<T> entities); 19 20 void Clear(); 21 T GetById(long Id); 22 T GetById(string Id); 23 T Get(Expression<Func<T, bool>> where); 24 IEnumerable<T> GetAll(); 25 IEnumerable<T> GetMany(Expression<Func<T, bool>> where); 26 IEnumerable<T> GetAllLazy(); 27 } 28 29 }
四、调用示例
1 var seoStuRepo = new SEOStudentMongoRepo(new MongoDBRepositoryContext(new MongoDBRepositoryContextSettings())); 2 3 seoStuRepo.Add(new SEOStudent() { 4 Name = "张冬林" 5 }); 6 7 seoStuRepo.Add(new SEOStudent() 8 { 9 Name = "张冬林" 10 }); 11 12 var seoStu = seoStuRepo.Get(p => p.Name=="张冬林"); 13 14 Console.ReadKey();
五、Web API 调用示例
1、IOC注册
1 #region mongoDB 2 builder.RegisterType<MongoDBRepositoryContextSettings>().As<IMongoDBRepositoryContextSettings>().SingleInstance(); 3 builder.RegisterType<MongoDBRepositoryContext>().As<IMongoDBRepositoryContext>().SingleInstance(); 4 builder.RegisterAssemblyTypes(typeof(SEOStudentMongoRepo).Assembly) 5 .Where(t => t.Name.EndsWith("MongoRepo")) 6 .AsImplementedInterfaces().InstancePerLifetimeScope(); 7 #endregion
2、Controller调用
1 private readonly ICommandBus _commandBus; 2 private readonly ISEOStudentMongoRepo _seoStudentMongoRepo; 3 4 public StudentController(ICommandBus commandBus, ISEOStudentMongoRepo seoStudentMongoRepo) 5 { 6 this._commandBus = commandBus; 7 this._seoStudentMongoRepo = seoStudentMongoRepo; 8 }
1 _seoStudentMongoRepo.Add(new SEOStudent() 2 { 3 Name = "张冬林" 4 }); 5 6 _seoStudentMongoRepo.Add(new SEOStudent() 7 { 8 Name = "张冬林" 9 }); 10 11 var seoStu = _seoStudentMongoRepo.Get(p => p.Name == "张冬林");
结果截图: