使用存储库模式时的MongoDB和大型数据集

使用存储库模式时的MongoDB和大型数据集,mongodb,linq,mongodb-.net-driver,Mongodb,Linq,Mongodb .net Driver,好的,我们正在使用MVC和MongoDB开发一个系统。在第一次开发时,我们认为遵循存储库模式可能是一个好主意(这是一个多么痛苦的问题!),下面的代码给出了当前实现的概念 MongoRepository类: public class MongoRepository { } public class MongoRepository<T> : MongoRepository, IRepository<T> where T : IEntity { private Mon

好的,我们正在使用MVC和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>();
    }
}
现在的问题是,如果集合有很多记录(准确地说是99905),那么如果字段中的数据不是很大,那么一切都可以正常工作。例如,我们的关键字段是一个5个字符的固定长度字符串,我可以跳过并使用此查询进行处理。但是,如果它类似于ClientDescription,则可以长得多,我可以从查询的前面(即第1页)进行“排序”精细和“获取”精细,但是当我使用Skip=99900&Take=10分页到末尾时,会出现以下内存错误:

发生“MongoDB.Driver.MongoCommandException”类型的异常 在MongoDB.Driver.dll中,但未在用户代码中处理

其他信息:命令聚合失败:异常:排序 超出了104857600字节的内存限制,但未选择加入 外部排序。正在中止操作。Pass allowDiskUse:对opt为真 在

好吧,我想这很容易理解。我在网上看了一眼,大部分建议都是使用聚合和“allowDiskUse:true”,但由于我在IRepository中使用IQueryable,我无法开始使用IAggregateFluent,因为您需要向IRepository公开MongoDB相关类,这将违反IoC原则

有没有办法强迫我能够使用它,或者有没有人知道我有没有办法在不违背国际奥委会原则的情况下访问IAggregateFluent

我感兴趣的一件事是为什么排序对第1页有效(Start=0,Take=10),但当我搜索到最后时却失败了。。。当然,我必须对所有内容进行排序,才能将第1页的项目按顺序排列,但不应该(Start=99900,Take=10)只需要相同数量的“排序”,MongoDB应该只向我发送最后5条左右的记录。当两种排序都完成时,为什么不发生此错误


回答

好的,在@craig wilson的帮助下,升级到最新版本的MongoDB C#drivers,并在MongoRepository中更改以下内容将解决此问题:

public IQueryable<T> SearchFor() {
    return _collection.AsQueryable<T>(new AggregateOptions { AllowDiskUse = true });
}
public IQueryable SearchFor(){
返回_collection.AsQueryable(新聚合选项{AllowDiskUse=true});
}

我收到System.MissingMethodException,但这是由于MongoDB驱动程序的其他副本也需要更新而导致的。

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


哦,这是新的:)我正在使用v2.2.0.262版本,唯一可用的签名是:
公共静态IMongoQueryable AsQueryable(此IMongoCollection集合)知道这一点很好!我将尝试升级。嗯,我现在遇到以下错误,我已尝试再次删除和添加引用eLinksWebPortal.dll中出现“System.MissingMethodException”类型的异常,但未在用户代码中处理其他信息:未找到方法:“MongoDB.Driver.Linq.IMongoQueryable
1 MongoDB.Driver.IMongoCollectionExtensions.AsQueryable”(MongoDB.Driver.IMongoCollection
1,MongoDB.Driver.AggregateOptions)”。感谢Craig:)当您遇到方法缺少异常之类的问题时,通常是因为您有多个项目引用库的不同版本。
MongoRepository<Client> clientCol = new MongoRepository<Client>();
tmpFinalList = clientCol
    .SearchFor()
    .OrderBy(tmpOrder) // tmpOrder = "ClientDescription DESC"
    .Skip(Start) // Start = 99900
    .Take(PageLength) // PageLength = 10
    .ToList();
public IQueryable<T> SearchFor() {
    return _collection.AsQueryable<T>(new AggregateOptions { AllowDiskUse = true });
}