web-dev-qa-db-ja.com

mongodbとC#の作業単位

MongoDBは作業単位などをサポートすることを想定していないことは知っていますが、意図(基準と同様)のみを格納するリポジトリを実装してからDBにコミットするとよいと思います。それ以外の場合は、リポジトリ内のすべてのメソッドで、DBへの接続を作成してから閉じる必要があります。 DBへの接続をBaseRepositoryクラスに配置すると、リポジトリを具象DBに結び付け、リポジトリをテストして、リポジトリを解決するIoCをテストすることは非常に困難です。

MongoDBでセッションを作成するのは悪い考えですか?接続ロジックをリポジトリから分離する方法はありますか?

これがRobConeryによるコードです。すべてのリクエストで常にDBに接続することをお勧めしますか?ベストプラクティスは何ですか?

もう1つあります。コレクションのインデックスを提供したいとします。以前はコンストラクターで行いましたが、Robのアプローチでは、これをそこで行うのは論理的ではないようです。

 using Norm;
    using Norm.Responses;
    using Norm.Collections;
    using Norm.Linq;

    public class MongoSession {

        private string _connectionString;

        public MongoSession() {
            //set this connection as you need. This is left here as an example, but you could, if you wanted,
            _connectionString = "mongodb://127.0.0.1/MyDatabase?strict=false";
        }

        public void Delete<T>(System.Linq.Expressions.Expression<Func<T, bool>> expression) where T : class, new() {
            //not efficient, NoRM should do this in a way that sends a single command to MongoDB.
            var items = All<T>().Where(expression);
            foreach (T item in items) {
                Delete(item);
            }
        }

        public void Delete<T>(T item) where T : class, new() {
            using(var db = Mongo.Create(_connectionString))
            {
              db.Database.GetCollection<T>().Delete(item);
            }
        }

        public void DeleteAll<T>() where T : class, new() {
            using(var db = Mongo.Create(_connectionString))
            {
              db.Database.DropCollection(typeof(T).Name);
            }
        }

        public T Single<T>(System.Linq.Expressions.Expression<Func<T, bool>> expression) where T : class, new() {
            T retval = default(T);
            using(var db = Mongo.Create(_connectionString))
            {
              retval = db.GetCollection<T>().AsQueryable()
                         .Where(expression).SingleOrDefault();
            }
            return retval;
        }

        public IQueryable<T> All<T>() where T : class, new() {
            //don't keep this longer than you need it.
            var db = Mongo.Create(_connectionString);
            return db.GetCollection<T>().AsQueryable();
        }

        public void Add<T>(T item) where T : class, new() {
            using(var db = Mongo.Create(_connectionString))
            {
              db.GetCollection<T>().Insert(item);
            }
        }

        public void Add<T>(IEnumerable<T> items) where T : class, new() {
            //this is WAY faster than doing single inserts.
            using(var db = Mongo.Create(_connectionString))
            {
              db.GetCollection<T>().Insert(items);
            }
        }

        public void Update<T>(T item) where T : class, new() {
            using(var db = Mongo.Create(_connectionString))
            {
              db.GetCollection<T>().UpdateOne(item, item);
            }
        }

        //this is just some sugar if you need it.
        public T MapReduce<T>(string map, string reduce) {
            T result = default(T);
            using(var db = Mongo.Create(_connectionString))
            {
            var mr = db.Database.CreateMapReduce();
            MapReduceResponse response =
                mr.Execute(new MapReduceOptions(typeof(T).Name) {
                    Map = map,
                    Reduce = reduce
                });
            MongoCollection<MapReduceResult<T>> coll = response.GetCollection<MapReduceResult<T>>();
            MapReduceResult<T> r = coll.Find().FirstOrDefault();
            result = r.Value;
            }
            return result;
        }

        public void Dispose() {
            _server.Dispose();
        }
    }
28
Yurii Hohan

接続の開閉についてはあまり心配しないでください。 MongoDB C#ドライバーは内部接続プールを維持するため、新しいMongoServerオブジェクトを作成するたびに実際の接続を開いたり閉じたりするオーバーヘッドが発生することはありません。

データロジックを公開するリポジトリインターフェイスを作成し、必要な場所に挿入されるMongoDB実装を構築できます。このようにして、MongoDB固有の接続コードは、IRepositoryのみを参照するアプリケーションから切り離されます。

MongoDBを使用して作業単位タイプのパターンを実装する場合は注意が必要です。 SQL Serverとは異なり、1つが失敗した場合にロールバックできるトランザクションに複数のクエリを参加させることはできません。

MongoDB、SQL Server、およびJSONが実装されているリポジトリパターンの簡単な例については、 NBlogストレージコード を確認してください。 Autofac IoCを使用して、具体的なリポジトリをASP.NETMVCアプリに挿入します。

18
Chris Fulstow

デザインパターンを研究している間、私は.NetCoreとMongoDBの基本的なリポジトリパターンを作成していました。 MongoDBのドキュメントを読んでいるときに、 MongoDBでのトランザクション に関する記事に出くわしました。記事では、次のように指定しています。

バージョン4.0以降、MongoDBはレプリカセットに対してマルチドキュメントトランザクションを実行する機能を提供します。

私が出くわしたインターチューブを見回すと ライブラリ これはMongoDBの作業単位パターンを実装するのに非常に優れています。

1
bschreck

Rob ConneryやNBlogストレージコードと同様の実装に興味があるが、mongodb csharpドライバー2.0(非同期)を使用している場合は、次を参照してください。

https://github.com/alexandre-spieser/mongodb-generic-repository

次に、BaseMongoRepositoryから継承するカスタムリポジトリを作成できます。

public interface ITestRepository : IBaseMongoRepository
{
    void DropTestCollection<TDocument>();
    void DropTestCollection<TDocument>(string partitionKey);
}

public class TestRepository : BaseMongoRepository, ITestRepository
{
    public TestRepository(string connectionString, string databaseName) : base(connectionString, databaseName)
    {
    }

    public void DropTestCollection<TDocument>()
    {
        MongoDbContext.DropCollection<TDocument>();
    }

    public void DropTestCollection<TDocument>(string partitionKey)
    {
        MongoDbContext.DropCollection<TDocument>(partitionKey);
    }
}
0
Darxtar