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

时间:2013-06-19 11:06:33

标签: c# asp.net mongodb

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

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

我与Entity Framework 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类非常简单,你可以看到Heros的集合被公开为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中添加或删除实体。然而,Find方法给出了编译器级错误。我的发现需要帮助,找到所有方法。我正在使用genrics,因为我需要我的repositry类来获取英雄,解决方案,项目,用户和类别等内容。

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();
    //}
}

4 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:2)

您似乎正在尝试对您的收藏品使用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);

答案 2 :(得分:1)

<强>通用

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);
        }
    }

<强>接口

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);
}

答案 3 :(得分:0)

我知道这是一篇相当古老的帖子,但我想与您分享在Github实施或下载为NuGet package

的MongoRepository项目

注意:我尝试实现MongoDB存储库的问题之一是不同的行为,具体取决于MongoDB驱动程序版本,或者与.NET Framework大致相同。 MongoRepository项目(在上面的链接中)解决了这个问题,使用不同版本的MongoDB驱动程序(检查MongoDB driver compatibility)的.net 3.5,4.0和4.5框架的不同代码版本,这非常有帮助。