2017-02-09 8 views
3

さて、私たちはMVC C#& MongoDBを使用してシステムを開発しています。最初に開発したときには、リポジトリのパターンに従うことをお勧めします(これはお尻の痛みです)。現在実装されていることを示すコードがあります。リポジトリパターン使用時の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ページは、DataTableが読み込まれるテーブルのJSONを出力するコントローラアクションにフィードするために使用されます。コレクションは(正確には99905)レコードをたくさん持っている場合は、データ場合

tmpFinalList = clientCol 
    .SearchFor() 
    .OrderBy(tmpOrder) // tmpOrder = "ClientDescription DESC" 
    .Skip(Start) // Start = 99900 
    .Take(PageLength) // PageLength = 10 
    .ToList(); 

さて問題は、すべてが正常に動作していること:LINQは、文字列の入力から構築することができるように、次はDynamicLinqを使用していることに注意してください私たちのキーフィールドは5文字の固定長の文字列であり、このクエリを使用してSkip and Take Fineを行うことができます。しかし、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..

これは分かりやすいと思います。私はインターネットを見ていて、ほとんどが提案されているすべてがアグリゲーションと "allowDiskUse:true"を使用することですが、IRepositoryでIQueryableを使用しているので、IAggregateFluent <を使用することはできません> MongoDB関連クラスをIRepositoryに公開する必要があるIoCプリンシパルに反対する

IQueryableにこれを強制的に使用させる方法はありますか、誰かがIoCプリンシパルを使わずにIAggregateFluentにアクセスする手段を知っていますか?

ソートが1ページ目(Start = 0、Take = 10)で動作するのはなぜですか?私が最後まで検索すると失敗します...確かに、 (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を渡すことができます。 `しかし知って良いのthats;パブリック静的IMongoQueryable AsQueryable (このIMongoCollection コレクションが)`:

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

+0

ああ、私がいたバージョンv2.2.0.262と利用可能な唯一の署名を使用しています:)新しいthatsの!私はアップグレードしようとします。 – Dwiea

+0

Hmmm今、次のエラーが表示されています。削除して再度参照を追加しようとしました.eLinksWebPortal.dllで 'System.MissingMethodException'タイプの例外が発生しましたが、ユーザーコードで処理されませんでした。 追加情報: 'MongoDB .Driver.Linq.IMongoQueryable'1 MongoDB.Driver.IMongoCollectionExtensions.AsQueryable(MongoDB.Driver.IMongoCollection'1 、MongoDB.Driver.AggregateOptions) '._ – Dwiea

+0

ヘルプCraigに感謝します:) – Dwiea

関連する問題