2009-02-14 35 views
15

Thực tiễn tốt nhất về thiết lập DataContext của tôi để dễ dàng truy cập vào các lớp LinqToSql mở rộng của tôi là gì?LinqToSql khai báo và khởi tạo thực hành tốt nhất của DataContext?

Ví dụ, tôi có một "tài khoản" thực thể trong dbml của tôi và tôi muốn thêm phương pháp để lớp đó như sau:

Partial Public Class User 

    Public Function GetUser(ByVal UserID as Integer) as User 
     'Do Work 
    End Function 

End Class 

Để truy cập vào DataContext của tôi, tôi sẽ phải khai báo nó bên trong phương pháp như vậy:

Partial Public Class User 

    Public Function GetUser(ByVal UserID as Integer) as User 
     Dim dc as New MyDataContext() 
     Return (From u in dc.Users Where u.ID = UserID).Single() 
    End Function 

End Class 

Tôi không muốn làm điều đó cho mọi phương pháp. Thông thường (nếu tôi không mở rộng các lớp dbml LinqToSql) Tôi chỉ có thể làm điều này:

Partial Public Class User 
    Private dc as MyDataContext 

    Public Sub New() 
     dc = new MyDataContext() 
    End Sub 

    Public Function GetUser(ByVal UserID as Integer) as User 
     Return (From u in dc.Users Where u.ID = UserID).Single() 
    End Function 

    Public Function GetAllUsers() as IEnumerable(Of User) 
     Return From u in dc.Users 
    End Function 

    'etc... 

End Class 

Điều này sẽ cho phép tôi để truy cập DataContext cho từng phương pháp mà không cần phải khai báo nó mới mỗi lần. Nhưng tất nhiên bạn không thể làm điều đó bởi vì dbml đã có một hàm tạo. Và việc thêm mã vào dbml luôn bị ghi đè nếu có bất kỳ điều gì thay đổi.

Bất kỳ ai có ý tưởng hay về cách tự lưu một số mã vượt quá ở đây?

TIA!

Trả lời

13

Trước tiên, hãy đảm bảo bạn đang xử lý DataContext của mình khi bạn hoàn tất! Anh ta có thể là một tên khốn nặng nề (chỉnh sửa không nặng để khởi tạo, nhưng nặng để giữ lại nếu bạn tiếp tục sử dụng nó mà không xử lý); bạn không muốn DataContexts cũ treo trong bộ nhớ.

Thứ hai, DataContext được dùng để đại diện cho một giao dịch lôgic đơn. Ví dụ. bạn nên tạo một cái mới mỗi khi bạn muốn bắt đầu một giao dịch mới và loại bỏ nó khi rằng giao dịch hoàn tất. Vì vậy, cho mục đích của bạn, đó là có thể là phạm vi của phương pháp GetUser. Nếu bạn có một loạt các cuộc gọi DB cần phải được thực hiện như một nhóm, tất cả họ nên sử dụng cùng một DC trước khi loại bỏ nó.

+1

Ngữ cảnh dữ liệu thực sự khá nhẹ, mặc dù nó có thể tham chiếu rất nhiều thực thể. Vứt bỏ nó để giải phóng các thực thể là một ý tưởng thực sự tốt. Nếu nó là một vật nặng, tôi sẽ nghiêng nhiều hơn để giữ nó xung quanh nên tôi không phải tái tạo nó. – tvanfosson

+0

@tvanfosson đó là ý của tôi; chỉnh sửa để làm cho điểm đó rõ ràng hơn. DC có khả năng mang theo rất nhiều trọng lượng với nó; tốt nhất để loại bỏ nó càng nhanh càng tốt. –

+0

Các đối số chống xử lý: http://stephenwalther.com/blog/archive/2008/08/20/asp-net-mvc-tip-34-dispose-of-your-datacontext-or-don-t.aspx –

0

Tôi nghĩ có lẽ vấn đề thực sự là User có lẽ không phải là địa điểm phù hợp cho cuộc gọi thành viên của cá thể GetUser.

+0

Ý bạn là gì? Bạn có thể giải thích thêm? – EdenMachine

11

Rex M said, văn bản dữ liệu được dự định sẽ được khởi tạo, sử dụng và xử lý cho mỗi giao dịch hợp lý. Các mẫu như thế này đôi khi được gọi là "đơn vị công việc".

Cách phổ biến nhất (mà tôi biết) để thực hiện việc này là khởi tạo datacontext của bạn trong một khối sử dụng. Tôi đã không được sử dụng VB trong một thời gian, nhưng nó sẽ giống như thế này:

Using dc As New MyDataContext() 
    user = (From u in dc.Users Where u.ID = UserID).Single() 
End Using 

Điều này không chỉ củng cố trông của một giao dịch/đơn vị công tác (thông qua hình dạng vật lý của code), nhưng nó đảm bảo gọi Dispose() trên datacontext của bạn khi khối kết thúc.

Xem this MSDN page:

Nói chung, một trường hợp DataContext được thiết kế để kéo dài một "đơn vị làm việc" tuy nhiên ứng dụng của bạn xác định rằng hạn.Một DataContext là nhẹ và không đắt tiền để tạo ra . Một ứng dụng LINQ to SQL điển hình tạo ra các trường hợp DataContext ở phạm vi phương thức hoặc thành viên của các lớp học ngắn ngủi mà đại diện cho một tập hợp logic các hoạt động cơ sở dữ liệu liên quan .

0

Có một vài cách khác nhau để bạn có thể thực hiện việc này, đó là cách thực hành tốt, tôi nghĩ vậy. Trước tiên, bạn có thể sử dụng mẫu Repository nơi bạn truy vấn Repository cho một đối tượng, nó đi ra ngoài cơ sở dữ liệu, truy xuất đối tượng - có thể tách nó khỏi ngữ cảnh dữ liệu hoặc giữ bối cảnh dữ liệu xung quanh tùy thuộc vào việc thực hiện Kho lưu trữ - và trả lại cho bạn. Các phương thức của nhà máy cho các đối tượng của bạn sẽ nằm trong Kho lưu trữ, không phải là các thực thể. Bạn có thể sử dụng phản chiếu và generics để giảm thiểu số lượng các phương pháp bạn phải thực hiện và giữ mã của bạn KHÔ.

Cách khác, và cách LINQtoSQL được dự định sử dụng tự nhiên IMHO, là tạo ngữ cảnh dữ liệu cho từng bộ hoạt động cơ sở dữ liệu mà bạn định thực hiện. Trong trường hợp này, việc tạo bối cảnh dữ liệu cũng xuất hiện bên ngoài thực thể, thường là trong lớp đang sử dụng các thực thể, không phải trong lớp dữ liệu. Bạn cũng có thể thêm các phương thức vào ngữ cảnh dữ liệu - làm cho bối cảnh dữ liệu thực tế của bạn trừu tượng và kế thừa từ nó - sử dụng sự phản chiếu một lần nữa, để thực hiện một số hàm khôi phục chung để bạn không phải lặp lại chúng. Có thể bạn sẽ phải sử dụng một mẫu cơ sở dữ liệu như ActiveRecords, trong đó các cột id luôn có cùng tên để thực hiện công việc này.

Mặt khác, bạn có thể xem bằng cách sử dụng nHibernate hoặc Lâu đài ActiveRecord thay vì sao chép một trong hai cách trên trong giải pháp của riêng bạn.

0

Có thể dễ dàng hơn nếu bạn chỉ rời khỏi lớp người dùng và cho phép IDE xử lý việc tạo của nó.

Thường thì tôi muốn có một lớp riêng biệt xử lý việc truy xuất dữ liệu. Giả sử bạn gọi nó là UserDataProvider và tất cả các cuộc gọi để có được một cá thể User cuối cùng đi qua lớp này.

Phương thức khởi tạo của UserDataProvider có thể khởi tạo một thể hiện toàn cục của đối tượng ngữ cảnh dữ liệu để tái sử dụng. Nó sẽ trông giống như thế này (trong C# và mã chưa được kiểm tra để trần với tôi):

public class UserDataProvider 
{ 
    private UserDataContext _data = null; 

    public UserDataProvider() 
    { 
     _data = new UserDataContext(); 
    } 

    public User GetUser(int userID) 
    { 
     return _data.Users.FirstOrDefault(u => u.UserID == userID); 
    } 
} 

Hoặc, bạn có thể đặt khởi tạo thuộc tính và truy cập tài sản đó để sử dụng ngữ cảnh dữ liệu.

public class UserDataProvider 
{ 
    private UserDataContext _dataContext; 

    private UserDataContext DataContext 
    { 
     get 
     { 
      if (_data == null) 
       _data = new UserDataContext(); 

      return _data; 
     } 
    } 

    public User GetUser(int userID) 
    { 
     return DataContext.Users.FirstOrDefault(u => u.UserID == userID); 
    } 
} 
Các vấn đề liên quan