好的,所以在工作中我们正在开发一个使用MVC C#的系统#& MongoDB。当第一次开发时,我们决定遵循Repository模式(屁股疼得厉害!)可能是一个好主意,下面是用于说明当前实现的代码的代码。使用存储库模式时的MongoDB和大型数据集
的MongoRepository类:
public class MongoRepository { }
public class MongoRepository<T> : MongoRepository, IRepository<T>
where T : IEntity
{
private MongoClient _client;
private IMongoDatabase _database;
private IMongoCollection<T> _collection;
public string StoreName {
get {
return typeof(T).Name;
}
}
}
public MongoRepository() {
_client = new MongoClient(ConfigurationManager.AppSettings["MongoDatabaseURL"]);
_database = _client.GetDatabase(ConfigurationManager.AppSettings["MongoDatabaseName"]);
/* misc code here */
Init();
}
public void Init() {
_collection = _database.GetCollection<T>(StoreName);
}
public IQueryable<T> SearchFor() {
return _collection.AsQueryable<T>();
}
}
的IRepository接口类:
public interface IRepository { }
public interface IRepository<T> : IRepository
where T : IEntity
{
string StoreNamePrepend { get; set; }
string StoreNameAppend { get; set; }
IQueryable<T> SearchFor();
/* misc code */
}
资源库,然后使用Ninject实例化,但不认为它会是这个样子(只是为了让这个简单的示例):
MongoRepository<Client> clientCol = new MongoRepository<Client>();
这里是用于搜索ch页面,这些页面用于输入控制器动作,该动作为具有DataTables的表格输出JSON以供读取。请注意,以下使用DynamicLinq,以便LINQ可以从字符串输入建:
tmpFinalList = clientCol
.SearchFor()
.OrderBy(tmpOrder) // tmpOrder = "ClientDescription DESC"
.Skip(Start) // Start = 99900
.Take(PageLength) // PageLength = 10
.ToList();
现在的问题是,如果集合有很多的纪录(99905是精确的)一切,如果数据正常工作在一个字段不是很大,例如我们的Key字段是一个5个字符的固定长度字符串,我可以跳过并采用这个查询罚款。然而,如果它是像ClientDescription可以更长时间我可以'排序'罚款和'采取'罚款从查询(即第1页),但是当我翻页结束Skip = 99900 & Take = 10它给出以下内存错误:
An exception of type 'MongoDB.Driver.MongoCommandException' occurred in MongoDB.Driver.dll but was not handled in user code
Additional information: Command aggregate failed: exception: Sort exceeded memory limit of 104857600 bytes, but did not opt in to external sorting. Aborting operation. Pass allowDiskUse:true to opt in..
好吧,以便我很容易理解。我在网上查了一下,其中大部分建议使用Aggregation和“allowDiskUse:true”,但是因为我在IRepository中使用IQueryable,所以我不能开始使用IAggregateFluent <>,因为您需要将MongoDB相关类暴露给IRepository,违背IoC校长。
有没有办法强制IQueryable使用这个或有人知道一种方式来访问IAggregateFluent而不违背IoC校长?
我感兴趣的一件事就是为什么排序适用于页面1(开始= 0,取= 10),但是当我搜索到最后时失败......当然,一切都必须按照我的顺序进行排序为了获得第1页的项目,但不应该(Start = 99900,Take = 10)只需要相同数量的“排序”,MongoDB应该只发送给我最近的5条记录。为什么这两种排序完成后都不会发生这种错误?
ANSWER
好了,所以的帮助下@克雷格 - 威尔逊升级到MongoDB的C#驱动程序的最新版本,并改变MongoRepository下面将解决这个问题:
public IQueryable<T> SearchFor() {
return _collection.AsQueryable<T>(new AggregateOptions { AllowDiskUse = true });
}
我得到了一个System.MissingMethodException,但这是由于需要更新的其他MongoDB驱动程序引起的。
哦,这就是新的:)我使用的版本v2.2.0.262和唯一可用的签名是:'公共静态IMongoQueryable AsQueryable已(这IMongoCollection 集合);'那好,虽然知道!我会尝试升级。 –
Dwiea
嗯我现在得到以下错误,我已经尝试删除并再次添加引用_EndsWebPortal.dll中发生类型'System.MissingMethodException'的异常,但没有在用户代码中处理 其他信息:找不到方法:'MongoDB .Driver.Linq.IMongoQueryable'1 MongoDB.Driver.IMongoCollectionExtensions.AsQueryable(MongoDB.Driver.IMongoCollection'1 ,MongoDB.Driver.AggregateOptions)'._ – Dwiea
感谢您的帮助Craig :) – Dwiea