2017-02-09 67 views
3

好的,所以在工作中我们正在开发一个使用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驱动程序引起的。

回答

5

从IMongoCollection创建IQueryable时,您可以传入允许您设置AllowDiskUse的AggregateOptions。

https://github.com/mongodb/mongo-csharp-driver/blob/master/src/MongoDB.Driver/IMongoCollectionExtensions.cs#L53

+0

哦,这就是新的:)我使用的版本v2.2.0.262和唯一可用的签名是:'公共静态IMongoQueryable AsQueryable已(这IMongoCollection 集合);'那好,虽然知道!我会尝试升级。 – Dwiea

+0

嗯我现在得到以下错误,我已经尝试删除并再次添加引用_EndsWebPortal.dll中发生类型'System.MissingMethodException'的异常,但没有在用户代码中处理 其他信息:找不到方法:'MongoDB .Driver.Linq.IMongoQueryable'1 MongoDB.Driver.IMongoCollectionExtensions.AsQueryable(MongoDB.Driver.IMongoCollection'1 ,MongoDB.Driver.AggregateOptions)'._ – Dwiea

+0

感谢您的帮助Craig :) – Dwiea

相关问题