好的,在工作中我们正在开发一个使用MVC C#& amp; MongoDB的。在第一次开发时,我们认为遵循Repository模式可能是一个好主意(屁股中的痛苦!),这里是代码,用于了解当前实现的内容。
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>();
以下是用于搜索页面的代码,用于输入控制器操作,该控制器操作为具有要读取的DataTables的表输出JSON。请注意,以下内容使用DynamicLinq,以便可以从字符串输入构建linq:
tmpFinalList = clientCol
.SearchFor()
.OrderBy(tmpOrder) // tmpOrder = "ClientDescription DESC"
.Skip(Start) // Start = 99900
.Take(PageLength) // PageLength = 10
.ToList();
现在的问题是,如果集合有很多记录(准确地说是99,905),如果字段中的数据不是非常大,一切正常,例如我们的Key字段是一个5字符的固定长度字符串我可以使用此查询跳过并使用。但是,如果像ClientDescription这样的东西可以更长,我可以排序&#39;好的&#39; Take&#39;从查询的前面(即第1页)精细但是当我用Skip = 99900&amp;取= 10它会出现以下内存错误:
类型&#39; MongoDB.Driver.MongoCommandException&#39;的例外情况发生了 在MongoDB.Driver.dll中但未在用户代码中处理
其他信息:命令聚合失败:异常:排序 超出内存限制104857600字节,但没有选择加入 外部排序。中止操作。传递allowDiskUse:true以选择 在..
好吧,我猜这很容易理解。我在网上看过,大多数建议是使用聚合和&#34; allowDiskUse:true&#34;但是因为我在IRepository中使用IQueryable,所以无法开始使用IAggregateFluent&lt;&gt;因为您需要将与MongoDB相关的类暴露给IRepository,这将违背IoC主体。
有没有办法强制IQueryable使用它,或者有没有人知道如何在不违反IoC主体的情况下访问IAggregateFluent?
我感兴趣的一件事是为什么排序适用于第1页(Start = 0,Take = 10)但是当我搜索结束时失败...当然一切都必须为我排序能够获得第1页的商品,但不应该(Start = 99900,Take = 10)只需要相同数量的排序&#39;和MongoDB应该只发送最后5个左右的记录。为什么在完成这两种排序时都不会发生此错误?
ANSWER
好的,在@ craig-wilson的帮助下升级到最新版本的MongoDB C#驱动程序并更改MongoRepository中的以下内容将解决问题:
public IQueryable<T> SearchFor() {
return _collection.AsQueryable<T>(new AggregateOptions { AllowDiskUse = true });
}
我收到了System.MissingMethodException,但这是由需要更新的MongoDB驱动程序的其他副本引起的。
答案 0 :(得分:5)
从IMongoCollection创建IQueryable时,您可以传入允许您设置AllowDiskUse的AggregateOptions。