简单的介绍一下,我使用MongoDB的场景。
我们现在的物联网环境下,有部分数据,采样频率为2000条记录/分钟,这样下来一天24*60*2000=2880000约等于300万条数据,以后必然还会增加。之前数据库使用的是mssql,对于数据库的压力很大,同时又需要保证历史查询的响应速度,这种情况下,在单表中数据量大,同时存在读写操作。不得已采用MongoDB来存储数据。如果使用MongoDB,则至少需要三台机器,两台实现读写分离,一台作为仲裁(当然条件不允许也可以不用),每台机器的内存暂时配置在16G,公司小,没办法,据说,使用这个MongoDB需要机器内存最少92G,我没有验证过,但是吃内存是公认的,所以内存绝对要保证,就算保证了,也不一定完全就没有意外发生。我们上面的这些特殊的数据是允许少量的丢失的,这些只是做分析使用的,几个月了,暂时还没出现数据丢失的情况,可能最新版本早就修复了吧,新手使用建议多看下官网上的说明。下面直接奔入主题:
一、安装部署和配置环境
1.安装部署mongo-server(V3.4)
参考 点击这里进入
这个时候不要启动,接着配置config文件
2.配置Config文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
dbpath=C:/Program Files/MongoDB/Server/3.4/bin/data/db logpath=C:/Program Files/MongoDB/Server/3.4/bin/data/log/master.log pidfilepath=C:/Program Files/MongoDB/Server/3.4/bin/master.pid directoryperdb=true logappend=true replSet=testrs bind_ip=10.1.5.25 port=27016 oplogSize=10000 noauth = true
storageEngine = wiredTiger wiredTigerCacheSizeGB = 2 syncdelay = 30 wiredTigerCollectionBlockCompressor = snappy |
以上是详细的配置参数,其中路径部分根据需要更改, 这里设置的oplogsize大小为10G,根据业务场景进行调整,另外auth权限为null,因为设置权限会增加服务开销,影响效率,最下面几行是内存引擎,可以控制副本集同步及内存限制,防止内存泄露。
3.启动mongo-server
4.添加副本集配置
1 2 3 4 5 6 7 8 9 10 11 |
conf= { "_id" : "testrs" , "members" : [ { "_id" : 0, "host" : "10.1.5.25:27016" }, { "_id" : 1, "host" : "10.1.5.26:27016" }, { "_id" : 2, "host" : "10.1.5.27:27016" } ] }
rs.initiate(conf) |
此时副本集集群配置已经完成,然后在命令行中输入:rs.status(),查看副本集状态,需要查看同步情况,可以输入命令:db.serverStatus().
5.设置副本集可读写
Rs.slaveOk()
6..NET操作mongo
连接设置,请参考个人封装Unitoon.Mongo代码所示。
7.性能对比
读写速度:Redis>Mongo>Mssqlserver
可容纳数据量:Mssqlserver~Mongo>Redis
存储数据类型:Mongo>Mssqlserver>Redis
Note:内存持续上升,内部没有内存回收机制,若限制内存 ,则可能出现查询速度变慢,数据丢失等问题,建议优化查询效率,建立索引
Db.test.ensureIndex({"username":1, "age":-1})
强制释放内存命令:db.runCommand({closeAllDatabases:1})
二、仓储设计
1.基类BaseEntity
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
namespace UnitoonIot.Mongo { /// <summary> /// 实体基类,方便生成ObjId /// </summary> [Serializable] [ProtoContract(ImplicitFields = ImplicitFields.AllPublic)] //[ProtoInclude(10, typeof(NormalHistory))] public class BaseEntity { //[BsonRepresentation(BsonType.ObjectId)] public ObjectId Id { get ; set ; }
/// <summary> /// 数据库名称 /// </summary> public string DbName { get ; set ; }
/// <summary> /// 给对象初值 /// </summary> public BaseEntity() { // this.ObjId = ObjectId.GenerateNewId().ToString(); //this.Id = ObjectId.NewObjectId().ToString(); } } } |
这里需要注意时间格式,MongoDB默认时间格式为国际时间,所以在写入数据时和读取数据时,时间格式要一致,此例中没有对时间进行特殊处理,由传入的时间格式确定。
2.Repository继承接口IMongoRepository
1 2 3 4 5 6 |
namespace UnitoonIot.Mongo { public interface IMongoRepository<TEntity> where TEntity : class { } } |
3.MongoRepository
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 |
using MongoDB.Driver; using MongoDB.Bson; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; using MongoDB.Bson.Serialization.Attributes; using MongoDB.Driver.Linq; using System.Configuration; using System.IO; using UnitoonIot.AppSetting;
namespace UnitoonIot.Mongo {
public class MongoDb { private static string ConnectionStringHost ; private static string UserName ; private static string Password; private static IMongoDatabase _db = null ; private static readonly object LockHelper = new object (); /// <summary> /// mongodb初始化 /// </summary> public static void Init() { ConnectionStringHost = "10.1.5.24:27016,10.1.5.24:27016,10.1.5.26:27017" ; //AppSettings.GetConfigValue("MongoHost");//"10.1.5.24:27016"; UserName = AppSettings.GetConfigValue( "MongoUserName" ); Password = AppSettings.GetConfigValue( "MongoPwd" ); } static MongoDb() {
} public static IMongoDatabase GetDb( string dbName, string options= null ) {
if (_db != null ) return _db; lock (LockHelper) {
if (_db != null ) return _db; var database = dbName; var userName = UserName; var password = Password; var authentication = string .Empty; var host = string .Empty; if (! string .IsNullOrWhiteSpace(userName)) { authentication = string .Concat(userName, ':' , password, '@' ); } if (! string .IsNullOrEmpty(options) && !options.StartsWith( "?" )) { options = string .Concat( '?' , options); }
host = string .IsNullOrEmpty(ConnectionStringHost) ? "localhost" : ConnectionStringHost; database = database ?? "testdb" ; //mongodb://[username:password@]host1[:port1][,host2[:port2],…[,hostN[:portN]]][/[database][?options]]
var conString = options!= null ? $ "mongodb://{authentication}{host}/{database}{options}" : $ "mongodb://{authentication}{host}/{database}" ;
var url = new MongoUrl(conString); var mcs = MongoClientSettings.FromUrl(url); mcs.MaxConnectionLifeTime = TimeSpan.FromMilliseconds(1000); var client = new MongoClient(mcs);
_db = client.GetDatabase(url.DatabaseName); } return _db; } } /// <summary> /// MongoDb 数据库操作类 /// </summary> public class MongoRepository<T>: IMongoRepository<T> where T : BaseEntity { #region readonly field /// <summary> /// 表名 /// </summary> private readonly IMongoCollection<T> _collection = null ; /// <summary> /// 数据库对象 /// </summary> private readonly IMongoDatabase _database; #endregion
/// <summary> /// 构造函数 /// </summary> public MongoRepository() { this ._database = MongoDb.GetDb(Activator.CreateInstance<T>().DbName, "readPreference =secondaryPreferred " ); //primaryPreferred/secondaryPreferred/nearest _collection = _database.GetCollection<T>( typeof (T).Name); }
#region 增加 /// <summary> /// 插入对象 /// </summary> /// <param name="t">插入的对象</param> public virtual T Insert(T t) { // var flag = ObjectId.GenerateNewId(); // t.GetType().GetProperty("Id").SetValue(t, flag); //t.Time = DateTime.Now;
_collection.InsertOne(t); return t; } /// <summary> /// 批量插入 /// </summary> /// <param name="ts">要插入的对象集合</param> public virtual IEnumerable<T> InsertBatch(IEnumerable<T> ts) { _collection.InsertMany(ts); return ts; }
/// <summary> /// 插入对象 /// </summary> /// <param name="t">插入的对象</param> public virtual void InsertAsync(T t) { //var flag = ObjectId.GenerateNewId(); // t.GetType().GetProperty("Id").SetValue(t, flag); // t.Time = DateTime.Now; _collection.InsertOneAsync(t); } /// <summary> /// 批量插入 /// </summary> /// <param name="ts">要插入的对象集合</param> public virtual void InsertBatchAsync(IEnumerable<T> ts) { _collection.InsertManyAsync(ts); } #endregion
#region 删除 /// <summary> /// 删除 /// </summary> /// <returns></returns> public virtual long Delete(T t) { var filter = Builders<T>.Filter.Eq( "Id" , t.Id); var result = _collection.DeleteOne(filter); return result.DeletedCount; } /// <summary> /// 删除 /// </summary> /// <returns></returns> public virtual void DeleteAsync(T t) { var filter = Builders<T>.Filter.Eq( "Id" , t.Id); _collection.DeleteOneAsync(filter); }
/// <summary> /// 按条件表达式删除 /// </summary> /// <param name="predicate">条件表达式</param> /// <returns></returns> public virtual long Delete(Expression<Func<T, bool >> predicate) { var result = _collection.DeleteOne(predicate); return result.DeletedCount; } /// <summary> /// 按条件表达式删除 /// </summary> /// <param name="predicate">条件表达式</param> /// <returns></returns> public virtual void DeleteAsync(Expression<Func<T, bool >> predicate) { _collection.DeleteOneAsync(predicate); }
/// <summary> /// 按条件表达式批量删除 /// </summary> /// <param name="predicate">条件表达式</param> /// <returns></returns> public virtual long DeleteBatch(Expression<Func<T, bool >> predicate) { var result = _collection.DeleteMany(predicate); return result.DeletedCount; } /// <summary> /// 按条件表达式批量删除 /// </summary> /// <param name="predicate">条件表达式</param> /// <returns></returns> public virtual void DeleteBatchAsync(Expression<Func<T, bool >> predicate) { _collection.DeleteManyAsync(predicate); }
/// <summary> /// 按检索条件删除 /// 建议用Builders<T>构建复杂的查询条件 /// </summary> /// <param name="filter">条件</param> /// <returns></returns> public virtual long Delete(FilterDefinition<T> filter) { var result = _collection.DeleteOne(filter); return result.DeletedCount; }
/// <summary> /// 按检索条件删除 /// 建议用Builders<T>构建复杂的查询条件 /// </summary> /// <param name="filter">条件</param> /// <returns></returns> public virtual void DeleteAsync(FilterDefinition<T> filter) { _collection.DeleteOneAsync(filter); } #endregion
#region 修改 /// <summary> /// 修改(Id不变) /// </summary> /// <returns></returns> public virtual long Update(T t) { var filterBuilder = Builders<T>.Filter; var filter = filterBuilder.Eq( "Id" ,t.Id); var update = _collection.ReplaceOne(filter, t, new UpdateOptions() { IsUpsert = true }); return update.ModifiedCount; } /// <summary> /// 修改(Id不变) /// </summary> /// <returns></returns> public virtual void UpdateAsync(T t) { var filterBuilder = Builders<T>.Filter; var filter = filterBuilder.Eq( "Id" , t.Id); _collection.ReplaceOneAsync(filter, t, new UpdateOptions() { IsUpsert = true });
}
/// <summary> /// 用新对象替换新文档 /// </summary> /// <param name="filter">查询条件</param> /// <param name="t">对象</param> /// <returns>修改影响文档数</returns> public virtual long Update(Expression<Func<T, bool >> filter, T t) { var update = _collection.ReplaceOne(filter, t, new UpdateOptions() { IsUpsert = true }); return update.ModifiedCount; }
/// <summary> /// 用新对象替换新文档 /// </summary> /// <param name="filter">查询条件</param> /// <param name="t">对象</param> /// <returns>修改影响文档数</returns> public virtual long Update(FilterDefinition<T> filter, T t) { var update = _collection.ReplaceOne(filter, t, new UpdateOptions() { IsUpsert = true }); return update.ModifiedCount; } /// <summary> /// 用新对象替换新文档 /// </summary> /// <param name="filter">查询条件</param> /// <param name="t">对象</param> /// <returns>修改影响文档数</returns> public virtual void UpdateAsync(Expression<Func<T, bool >> filter, T t) { _collection.ReplaceOneAsync(filter, t, new UpdateOptions() { IsUpsert = true });
} /// <summary> /// 用新对象替换新文档 /// </summary> /// <param name="filter">查询条件</param> /// <param name="t">对象</param> /// <returns>修改影响文档数</returns> public virtual void UpdateAsync(FilterDefinition<T> filter, T t) { _collection.ReplaceOneAsync(filter, t, new UpdateOptions() { IsUpsert = true });
} /// <summary> /// 根据Id和条件文档 /// </summary> /// <param name="update">修改条件-形如:Builders/<T/>.Update.Set(filed, value)</param> /// <param name="id">对象Id</param> /// <returns>修改影响文档数</returns> public virtual long Update( string id, UpdateDefinition<T> update) { var filterBuilder = Builders<T>.Filter; var filter = filterBuilder.Eq( "Id" , new ObjectId(id)); var result = _collection.UpdateOne(filter, update, new UpdateOptions() { IsUpsert = true }); return result.ModifiedCount; } /// <summary> /// 根据Id和条件文档 /// </summary> /// <param name="update">修改条件-形如:Builders/<T/>.Update.Set(filed, value)</param> /// <param name="id">对象Id</param> /// <returns>修改影响文档数</returns> public virtual void UpdateAsync( string id, UpdateDefinition<T> update) { var filterBuilder = Builders<T>.Filter; var filter = filterBuilder.Eq( "Id" , new ObjectId(id)); _collection.UpdateOneAsync(filter, update, new UpdateOptions() { IsUpsert = true }); } /// <summary> /// 根据条件修改文档 /// </summary> /// <param name="update">修改条件-形如:Builders/<T/>.Update.Set(filed, value)</param> /// <param name="filter">查询条件Builders/<T/>.Filter.Eq(filed, value)</param> /// <returns>修改影响文档数</returns> public virtual void Update(UpdateDefinition<T> update,Expression<Func<T, bool >> filter) { _collection.UpdateOne(filter, update, new UpdateOptions() { IsUpsert = true }); } /// <summary> /// 根据条件修改文档 /// </summary> /// <param name="update">修改条件-形如:Builders/<T/>.Update.Set(filed, value)</param> /// <param name="filter">查询条件Builders/<T/>.Filter.Eq(filed, value)</param> /// <returns>修改影响文档数</returns> public virtual long Update(UpdateDefinition<T> update, FilterDefinition<T> filter) { var result = _collection.UpdateOne(filter, update, new UpdateOptions() { IsUpsert = true }); return result.ModifiedCount; } /// <summary> /// 根据条件修改文档 /// </summary> /// <param name="update">修改条件-形如:Builders/<T/>.Update.Set(filed, value)</param> /// <param name="filter">查询条件Builders/<T/>.Filter.Eq(filed, value)</param> /// <returns>修改影响文档数</returns> public virtual void UpdateAsync(UpdateDefinition<T> update, Expression<Func<T, bool >> filter) { _collection.UpdateOneAsync(filter, update, new UpdateOptions() { IsUpsert = true }); } /// <summary> /// 根据条件修改文档 /// </summary> /// <param name="update">修改条件-形如:Builders/<T/>.Update.Set(filed, value)</param> /// <param name="filter">查询条件Builders/<T/>.Filter.Eq(filed, value)</param> /// <returns>修改影响文档数</returns> public virtual void UpdateAsync(UpdateDefinition<T> update, FilterDefinition<T> filter) { _collection.UpdateOneAsync(filter, update, new UpdateOptions() { IsUpsert = true }); }
/// <summary> /// 根据条件批量修改文档 /// </summary> /// <param name="update">修改条件-形如:Builders/<T/>.Update.Set(filed, value)</param> /// <param name="filter">查询条件Builders/<T/>.Filter.Eq(filed, value)</param> /// <returns>修改影响文档数</returns> public virtual long UpdateBatch(UpdateDefinition<T> update, Expression<Func<T, bool >> filter) { var result = _collection.UpdateMany(filter, update, new UpdateOptions() { IsUpsert = true }); return result.ModifiedCount; }
/// <summary> /// 根据条件批量修改文档 /// </summary> /// <param name="update">修改条件-形如:Builders/<T/>.Update.Set(filed, value)</param> /// <param name="filter">查询条件Builders/<T/>.Filter.Eq(filed, value)</param> /// <returns>修改影响文档数</returns> public virtual long UpdateBatch(UpdateDefinition<T> update, FilterDefinition<T> filter) { var result = _collection.UpdateMany(filter, update, new UpdateOptions() { IsUpsert = true }); return result.ModifiedCount; } /// <summary> /// 根据条件批量修改文档 /// </summary> /// <param name="update">修改条件-形如:Builders/<T/>.Update.Set(filed, value)</param> /// <param name="filter">查询条件Builders/<T/>.Filter.Eq(filed, value)</param> /// <returns>修改影响文档数</returns> public virtual void UpdateBatchAsync(UpdateDefinition<T> update, Expression<Func<T, bool >> filter) { _collection.UpdateManyAsync(filter, update, new UpdateOptions() { IsUpsert = true }); }
/// <summary> /// 根据条件批量修改文档 /// </summary> /// <param name="update">修改条件-形如:Builders/<T/>.Update.Set(filed, value)</param> /// <param name="filter">查询条件Builders/<T/>.Filter.Eq(filed, value)</param> /// <returns>修改影响文档数</returns> public virtual void UpdateBatchAsync(UpdateDefinition<T> update, FilterDefinition<T> filter) { _collection.UpdateManyAsync(filter, update, new UpdateOptions() { IsUpsert = true }); } #endregion
#region 查询
#region GetCollection
/// <summary> /// 获取操作对象的IMongoCollection集合,强类型对象集合 /// </summary> /// <returns></returns> public virtual IMongoCollection<T> GetCollection() { return _database.GetCollection<T>( typeof (T).Name); }
#endregion
#region GetSingle /// <summary> /// 查询数据库,检查是否存在指定ID的对象 /// </summary> /// <param name="id">对象的ID值</param> /// <returns>存在则返回指定的对象,否则返回Null</returns> public virtual T GetById( string id) { var filterBuilder = Builders<T>.Filter; var filter = filterBuilder.Eq( "Id" , new ObjectId(id)); var data = _collection.Find(filter).FirstOrDefault(); return data; } /// <summary> /// 查询数据库,检查是否存在指定ID的对象 /// </summary> /// <param name="id">对象的ID值</param> /// <returns>存在则返回指定的对象,否则返回Null</returns> public virtual async Task<T> GetAsyncById( string id) { var filterBuilder = Builders<T>.Filter; var filter = filterBuilder.Eq( "Id" , new ObjectId(id)); var data = await _collection.FindAsync(filter); return await data.SingleOrDefaultAsync(); } /// <summary> /// 查询数据 /// </summary> /// <param name="filter">过滤条件</param> /// <returns></returns> public virtual T Get(FilterDefinition<T> filter) { return _collection.Find(filter).FirstOrDefault(); } /// <summary> /// 查询数据 /// </summary> /// <param name="filter">条件表达式</param> /// <returns></returns> public virtual T Get(Expression<Func<T, bool >> filter) { return _collection.Find(filter).FirstOrDefault(); } /// <summary> /// 查询数据 /// </summary> /// <param name="filter">过滤条件</param> /// <returns></returns> public virtual async Task<T> GetAsync(FilterDefinition<T> filter) { var data = await _collection.FindAsync(filter); return await data.SingleOrDefaultAsync(); } /// <summary> /// 查询数据 /// </summary> /// <param name="filter">条件表达式</param> /// <returns></returns> public virtual async Task<T> GetAsync(Expression<Func<T, bool >> filter) { var data = await _collection.FindAsync(filter); return await data.SingleOrDefaultAsync(); }
#endregion
#region GetMany /// <summary> /// 查询部分数据 /// </summary> /// <param name="filter">过滤条件</param> /// <returns></returns> public virtual IEnumerable<T> GetMany(FilterDefinition<T> filter) { return _collection.Find(filter).ToEnumerable(); }
/// <summary> /// 查询部分数据 /// </summary> /// <param name="filter">条件表达式</param> /// <returns></returns> public virtual IEnumerable<T> GetMany(Expression<Func<T, bool >> filter) { //return _collection.AsQueryable().Where(filter).ToList(); //return _collection.AsQueryable().Where(filter); return _collection.Find(filter).ToEnumerable(); //.ToEnumerable(); }
/// <summary> /// 查询部分数据 /// </summary> /// <param name="filter">过滤条件</param> /// <returns></returns> public virtual async Task<IEnumerable<T>> GetManyAsync(FilterDefinition<T> filter) { var data = await _collection.FindAsync(filter); return await data.ToListAsync(); }
/// <summary> /// 查询部分数据 /// </summary> /// <param name="filter">过滤条件</param> /// <returns></returns> public virtual async Task<IEnumerable<T>> GetManyAsync(Expression<Func<T, bool >> filter) { var data = await _collection.FindAsync(filter); return await data.ToListAsync(); }
#endregion
#region GetAll
/// <summary> /// 查询所有记录,复杂查询直接用Linq处理(避免全表扫描) /// </summary> /// <returns>要查询的对象</returns> public virtual IEnumerable<T> GetAll() { var data = _collection.AsQueryable(); return data.ToEnumerable(); } /// <summary> /// 查询所有记录,复杂查询直接用Linq处理(避免全表扫描) /// </summary> /// <returns>要查询的对象</returns> public virtual async Task<IEnumerable<T>> GetAllAsync() { var data = _collection.AsQueryable(); return await data.ToListAsync(); }
/// <summary> /// 查询所有记录,复杂查询直接用Linq处理(避免全表扫描) /// </summary> /// <returns>要查询的对象</returns> public virtual IQueryable<T> GetAllQueryable() { return _collection.AsQueryable(); }
#endregion
#region MapReduce /// <summary> /// MapReduce /// </summary> /// <returns>返回一个List列表数据</returns> public IEnumerable<T> GetMap(BsonJavaScript map,BsonJavaScript reduce) { return _collection.MapReduce<T>(map,reduce).ToList(); }
#endregion
#endregion }
} |
好了,就介绍到这里。
原文链接:http://HdhCmsTestcnblogs测试数据/lianming37/p/7606707.html
查看更多关于windows7下使用MongoDB实现仓储设计的详细内容...