2011-08-23 20 views
27

Tôi biết MongoDB không được hỗ trợ đơn vị công việc, v.v. Nhưng tôi nghĩ sẽ tốt hơn nếu triển khai kho lưu trữ chỉ có ý định (tương tự tiêu chí) và sau đó cam kết chúng cho DB. Nếu không, trong mọi phương thức trong kho lưu trữ của bạn, bạn phải tạo kết nối đến DB và sau đó đóng nó lại. Nếu chúng ta đặt kết nối tới DB trong một số lớp BaseRepository, thì chúng ta kết buộc kho lưu trữ của chúng ta với DB cụ thể và thật sự rất khó để kiểm tra các kho lưu trữ, để kiểm tra IoC giải quyết các kho lưu trữ.Đơn vị công việc ở mongodb và C#

Tạo phiên trong MongoDB là một ý tưởng tồi? Có cách nào để tách logic kết nối khỏi kho lưu trữ không?

Đây là một số mã của Rob Conery. Bạn có nên luôn kết nối với DB của mình theo mọi yêu cầu không? Thực hành tốt nhất là gì?

Còn một điều nữa. Hãy tưởng tượng tôi muốn cung cấp một chỉ mục cho một bộ sưu tập. Trước đây tôi đã làm trong một nhà xây dựng nhưng với cách tiếp cận của Rob này có vẻ ngoài logic để làm điều đó ở đó.

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

Làm thế nào về tiêm phụ thuộc thông qua một khuôn khổ (hoặc tự viết)? – DrColossos

+0

@DrColossos, Thực ra tôi sử dụng một framework có tên Castle.Windsor. Tôi đã nhìn thấy một số mã của Rob Conery mô phỏng phiên nhưng ông kết nối với DB trên mỗi tạo/cập nhật/xóa/tìm kiếm và tôi không nếu nó là tối ưu –

Trả lời

17

Đừng lo lắng quá nhiều về việc mở và đóng kết nối. Trình điều khiển C# MongoDB duy trì một nhóm kết nối nội bộ, vì vậy bạn sẽ không phải chịu chi phí đầu vào của việc mở và đóng các kết nối thực tế mỗi khi bạn tạo một đối tượng MongoServer mới.

Bạn có thể tạo giao diện kho lưu trữ logic dữ liệu của bạn và xây dựng triển khai MongoDB được chèn vào nơi cần. Bằng cách đó, mã kết nối cụ thể MongoDB được loại bỏ khỏi ứng dụng của bạn, mà chỉ thấy IRepository.

Hãy cẩn thận khi cố gắng triển khai mẫu kiểu đơn vị hoạt động với MongoDB. Không giống như SQL Server, bạn không thể tranh thủ nhiều truy vấn trong một giao dịch có thể được khôi phục nếu một lỗi không thành công.

Để có ví dụ đơn giản về mẫu lưu trữ có triển khai MongoDB, SQL Server và JSON, hãy xem NBlog storage code. Nó sử dụng Autofac IoC để chèn kho lưu trữ bê tông vào một ứng dụng ASP.NET MVC.

+0

Chris, cảm ơn bạn đã trả lời. Tôi đã xem xét mã của bạn cho kho lưu trữ. Trong constructor bạn tạo và giữ trong suốt các đối tượng là một cá thể của MongoServer. Ví dụ, mã kiểm thử Unit của bạn cho IoC phải giải quyết một số kho lưu trữ. Điều đó có nghĩa là máy chủ xây dựng của bạn có thể bị lỗi vì không có quá trình mongos trong đó. Và thậm chí về mặt khái niệm, dường như không có gì là đúng là –

+0

@Hohhi là những bài kiểm tra tích hợp hơn là kiểm tra đơn vị, họ mong đợi (và yêu cầu) một quá trình mongod chạy cục bộ để vượt qua. –

+0

Nơi thích hợp để áp dụng chỉ mục là gì? –

0

Nếu bạn quan tâm đến một thực hiện tương tự để mã lưu trữ nhưng sử dụng trình điều khiển MongoDB CSharp 2.0 (có nghĩa là không đồng bộ) của Rob Connery và NBlog, bạn có thể xem xét:

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

Sau đó bạn có thể viết một kho lưu trữ tùy chỉnh kế thừa từ 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); 
    } 
} 
Các vấn đề liên quan