如何实现针对mongodb的通用存储库

本文关键字:mongodb 存储 何实现 实现 | 更新日期: 2023-09-27 18:18:57

我是mongodb的新手,我正在为一个新项目开发mvc4 web应用程序。

我想使用存储库模式,将与mongodb上下文进行数据库级通信。

简单的接口,我已经使用实体框架4.0如下。查找成员对我来说是有问题的地方。我不知道如何继续与他们与mongodb上下文。

public interface IRepository<T> where T : class
{
    void Add(T entity);
    void Remove(T entity);
    IQueryable<T> Find(Expression<Func<T, bool>> predicate);
    //IQueryable<T> FindAll();
}

我有一个非常简单的模型,叫做Hero,它来自ImongoEntity,它提供了一个名为accessId的成员。

public class Hero : MongoDB.Kennedy.IMongoEntity
{
    public ObjectId _id { get; set; }
    public string Name { get; set; }
    public string Alias { get; set; }
    public string _accessId { get; set;}
}

Context类是非常简单的,你可以看到英雄的集合被暴露为IQueryable属性。

public class MongoDataConetext: MongoDB.Kennedy.ConcurrentDataContext
{
    public MongoDataConetext(string databaseName, string serverName="localhost") : base(databaseName, serverName)
    {
    }
    public IQueryable<Hero> Heros {
        get {
            return base.GetCollection<Hero>().AsQueryable();
        }
    }
}

现在在我的存储库中最简单的方法是添加和删除它们成功地与mongodb上下文交谈,并从mongodb中添加或删除实体。然而,找到方法给了我编译器级别的错误。我需要帮助我的查找和查找所有方法。我之所以使用通用型,是因为我需要我的存储库类来存储英雄、解决方案、项目、用户和类别等实体。

public class Repository<T> : IRepository<T> where T : class, IMongoEntity
{
    private readonly MongoDataConetext _ctx;
    public Repository(MongoDataConetext ctx)
    {
        _ctx = ctx;
    }
    public void Add(T entity)
    {
        _ctx.Save(entity);

    }
    public void Remove(T entity)
    {
        _ctx.Delete(entity);
    }
    public IQueryable<T> Find(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
    {
        _ctx.Heros.Where(predicate);
        //throw new NotImplementedException();
    }
    //public IQueryable<T> FindAll()
    //{
    //    throw new NotImplementedException();
    //}
}

如何实现针对mongodb的通用存储库

如果您对类似于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);
    }
}

更新:它现在可以作为自己的nuget包使用:

Install-Package MongoDbGenericRepository

看起来您正在尝试对您的集合使用LINQ。这是完美的。如果你只是公开一个IQueryable属性,而不是编写一个Find()方法,你可以更容易地做到这一点。

这是你上面的一个例子:

public class HeroRepository : IRepository<Heros> where T : class, IMongoEntity
{
    // ...
    public IQueryable<Heros> Heros 
    {
        get 
        { 
            return _ctx.GetCollection<Heros>().AsQueryable(); 
            // Careful there, doing this from memory, may be a little off...
        }
    }
}

当然,当你使用这个类时,只需:

var r = new HeroRepository();
var heros = r.Heros.Where(r => r.SuperPowerLevel > 20);

通用

public class MongoDatabase<T> : IDatabase<T> where T : class, new()
    {
        private static string connectionString = "connectionString";
        private static IMongoClient server = new MongoClient(connectionString);
        private string collectionName;
        private IMongoDatabase db;
        protected IMongoCollection<T> Collection
        {
            get
            {
                return db.GetCollection<T>(collectionName);
            }
            set
            {
                Collection = value;
            }
        }
        public MongoDatabase(string collection)
        {
            collectionName = collection;
            db = server.GetDatabase(MongoUrl.Create(connectionString).DatabaseName);
        }
        public IMongoQueryable<T> Query
        {
            get
            {
                return Collection.AsQueryable<T>();
            }
            set
            {
                Query = value;
            }
        }
        public T GetOne(Expression<Func<T, bool>> expression)
        {
            return Collection.Find(expression).SingleOrDefault();
        }
        public T FindOneAndUpdate(Expression<Func<T, bool>> expression, UpdateDefinition<T> update, FindOneAndUpdateOptions<T> option)
        {
            return Collection.FindOneAndUpdate(expression, update, option);
        }
        public void UpdateOne(Expression<Func<T, bool>> expression, UpdateDefinition<T> update)
        {
            Collection.UpdateOne(expression, update);
        }
        public void DeleteOne(Expression<Func<T, bool>> expression)
        {
            Collection.DeleteOne(expression);
        }
        public void InsertMany(IEnumerable<T> items)
        {
            Collection.InsertMany(items);
        }
        public void InsertOne(T item)
        {
            Collection.InsertOne(item);
        }
    }

İnterface

public interface IDatabase<T> where T : class, new()
{
    IMongoQueryable<T> Query { get; set; }
    T GetOne(Expression<Func<T, bool>> expression);
    T FindOneAndUpdate(Expression<Func<T, bool>> expression, UpdateDefinition<T> update, FindOneAndUpdateOptions<T> option);
    void UpdateOne(Expression<Func<T, bool>> expression, UpdateDefinition<T> update);
    void DeleteOne(Expression<Func<T, bool>> expression);
    void InsertMany(IEnumerable<T> items);
    void InsertOne(T item);
}

我知道这是一篇相当旧的文章,但我想与您分享在Github上实现的MongoRepository项目或作为NuGet包下载

注意:我试图实现MongoDB存储库的问题之一是不同的行为取决于MongoDB驱动程序版本或或多或少相同,. net框架。MongoRepository项目(在上面的链接中)已经用。net 3.5, 4.0和4.5框架的不同代码版本解决了这个问题,这些框架使用不同版本的MongoDB驱动程序(检查MongoDB驱动程序兼容性),这非常有帮助。