2012-04-23 69 views
7

Tôi đang sử dụng LINQ to Entities và gần đây, tôi thấy rằng rất nhiều folks giới thiệu gói các DataContext trong một tuyên bố sử dụng như thế này:sử dụng đúng cách "Sử dụng" tuyên bố cho DataContext

Using(DataContext db = new DataContext) { 
    var xx = db.customers; 
} 

này có ý nghĩa . Tuy nhiên, tôi không chắc chắn cách kết hợp thực tiễn này trong mô hình của mình. Ví dụ: Tôi có một giao diện (chúng ta hãy gọi nó là khách hàng) và nó được thực hiện bởi một kho lưu trữ như thế này:

namespace Models 
{ 
    public class rCustomer : iCustomer 
    { 

     readonly DataContext db = new DataContext(); 

     public customer getCustomer(Guid id) 
     { 
      return db.customers.SingleOrDefault(por => por.id == id); 
     } 

     public iQueryable<customer> getTopCustomers() 
     { 
      return db.customers.Take(10); 
     } 

     //******************************************* 
     //more methods using db, including add, update, delete, etc. 
     //******************************************* 

    } 
} 

Sau đó, để tận dụng lợi thế của việc sử dụng, tôi sẽ cần phải thay đổi phương pháp để trông giống như này:

namespace Models 
{ 
    public class rCustomer : iCustomer 
    { 
     public customer getCustomer(Guid id) 
     { 
      using(DataContext db = new DataContext()) {  
       return db.customers.SingleOrDefault(por => por.id == id); 
      } 
     } 

     public iQueryable<customer> getTopCustomers() 
     { 
      using(DataContext db = new DataContext()) {  
       return db.customers.Take(10); 
      } 
     } 

     //******************************************* 
     //more methods using db 
     //******************************************* 

    } 
} 

Câu hỏi của tôi là: đề xuất sử dụng "Sử dụng" thực sự tốt? Hãy xem xét rằng thay đổi này sẽ là một thay đổi lớn, tôi có khoảng 25 giao diện/kho lưu trữ combo, và mỗi có khoảng 20-25 phương pháp, chưa kể đến việc cần phải kiểm tra lại mọi thứ sau khi kết thúc. Có cách nào khác không?

Cảm ơn!

Edgar.

+0

Điều đó tùy thuộc vào cách bạn đang sử dụng lớp học đó. – SLaks

+0

Nếu bạn biết những gì 'sử dụng' là làm nó tùy thuộc vào bạn để quyết định xem nó có xứng đáng với bạn hay không. – gdoron

Trả lời

5

Bạn có thể triển khai nhà máy cơ sở dữ liệu sẽ khiến DbContext của bạn đang được sử dụng lại.

Bạn có thể đạt được điều này như sau:

DatabaseFactory lớp:

public class DatabaseFactory : Disposable, IDatabaseFactory 
{ 
    private YourEntities _dataContext; 
    public YourEntities Get() 
    { 
     return _dataContext ?? (_dataContext = new YourEntities()); 
    } 
    protected override void DisposeCore() 
    { 
     if (_dataContext != null) 
      _dataContext.Dispose(); 
    } 
} 

Trích của lớp cơ sở Repository:

public abstract class Repository<T> : IRepository<T> where T : class 
{ 
    private YourEntities _dataContext; 
    private readonly IDbSet<T> _dbset; 
    protected Repository(IDatabaseFactory databaseFactory) 
    { 
     DatabaseFactory = databaseFactory; 
     _dbset = DataContext.Set<T>(); 
    } 

    protected IDatabaseFactory DatabaseFactory 
    { 
     get; 
     private set; 
    } 

    protected YourEntities DataContext 
    { 
     get { return _dataContext ?? (_dataContext = DatabaseFactory.Get()); } 
    } 

của bảng của bạn lớp kho:

public class ApplicationRepository : Repository<YourTable>, IYourTableRepository 
{ 
    private YourEntities _dataContext; 

    protected new IDatabaseFactory DatabaseFactory 
    { 
     get; 
     private set; 
    } 

    public YourTableRepository(IDatabaseFactory databaseFactory) 
     : base(databaseFactory) 
    { 
     DatabaseFactory = databaseFactory; 
    } 

    protected new YourEntities DataContext 
    { 
     get { return _dataContext ?? (_dataContext = DatabaseFactory.Get()); } 
    } 

    } 
    public interface IYourTableRepository : IRepository<YourTable> 
    { 
    } 
} 

Điều này làm việc hoàn hảo cùng với việc xây dựng AutoFac constructor là tốt.

2

Lớp DataContext được bao bọc trong câu lệnh Sử dụng vì nó triển khai giao diện IDisposable.

Nội bộ cho DataContext đang sử dụng đối tượng SqlConnection và đối tượng SqlCommand. Để phát hành chính xác các kết nối này trở lại Sql Connection Pool, chúng cần được xử lý.

Bộ thu gom rác cuối cùng sẽ thực hiện việc này, nhưng sẽ mất hai lần truy cập do cách thức đối tượng IDisposable được quản lý.

Rất khuyến khích rằng Vứt bỏ được gọi và tuyên bố Sử dụng là cách hay để thực hiện việc này.

đọc những liên kết này để giải thích sâu sắc hơn:

http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/2625b105-2cff-45ad-ba29-abdd763f74fe/

http://www.c-sharpcorner.com/UploadFile/DipalChoksi/UnderstandingGarbageCollectioninNETFramework11292005051110AM/UnderstandingGarbageCollectioninNETFramework.aspx

3

Xét mã được cung cấp tôi thấy, bạn esplicitly sử dụng readonly DataContext db = new DataContext(); như một biến toàn cầu, vì vậy bạn cân nhắc để có đối tượng đời cùng với tuổi thọ lớp học rCustomer của bạn.

Nếu điều này là đúng, những gì bạn có thể làm, thay vì viết lại tất cả mọi thứ, bạn có thể thực hiện IDisposable và bên Dispose() đang giống như

private void Dispose() 
{ 
    if(db != null) 
     db.Dispose(); 
} 

Hope this helps.

2

Cách khác là làm cho lớp rCustomer của bạn triển khai IDisposable và sau đó trong phương thức Dispose, bạn có thể gọi Vứt bỏ trên DataContext nếu nó không rỗng. Tuy nhiên, điều này chỉ đẩy mẫu dùng một lần ra khỏi lớp rCustomer của bạn, vào bất kỳ loại nào đang sử dụng rCustomer.

3

Như những người khác đã đề cập, điều quan trọng là bối cảnh dữ liệu phải được xử lý. Tôi sẽ không đi sâu hơn nữa.

tôi thấy ba thiết kế có thể cho các lớp để đảm bảo rằng những bối cảnh được xử lý:

  1. Giải pháp thứ hai mà bạn cung cấp mà bạn tạo ra một bối cảnh dữ liệu trong phạm vi của mỗi phương pháp rCustomer mà cần nó để mỗi datacontext nằm trong khối using.
  2. Giữ ngữ cảnh dữ liệu dưới dạng một biến mẫu và có rCustomer triển khai IDisposable sao cho khi rCustomer được xử lý, bạn có thể bỏ ngữ cảnh dữ liệu của nó. Điều này có nghĩa là tất cả các trường hợp rCustomer sẽ cần phải được bao bọc trong các khối using.
  3. Chuyển trường hợp ngữ cảnh dữ liệu hiện có thành rCustomer thông qua hàm tạo của nó. Nếu bạn làm điều này thì rCustomer sẽ không chịu trách nhiệm xử lý nó, người dùng của lớp sẽ. Điều này sẽ cho phép bạn sử dụng một ngữ cảnh dữ liệu duy nhất trên một số trường hợp của rCustomer hoặc với một số lớp khác nhau cần truy cập vào ngữ cảnh dữ liệu. Điều này có lợi thế (ít chi phí liên quan đến việc tạo ra bối cảnh dữ liệu mới) và nhược điểm (dấu chân bộ nhớ lớn hơn vì bối cảnh dữ liệu có xu hướng giữ khá nhiều bộ nhớ thông qua cache và tương tự).

Tôi thành thật nghĩ rằng tùy chọn # 1 là một điều khá tốt, miễn là bạn không nhận thấy nó hoạt động quá chậm (tôi muốn thời gian/hồ sơ nếu bạn nghĩ rằng nó gây ra vấn đề). Do kết nối tổng hợp nó không phải là tất cả những gì xấu. Nếu có, tôi sẽ chọn # 3 làm lựa chọn tiếp theo. # 2 không phải là xa phía sau, nhưng nó có thể sẽ là một chút khó xử và bất ngờ cho các thành viên khác trong nhóm của bạn (nếu có).

Các vấn đề liên quan