Đối tượng kinh doanh trong lớp truy cập dữ liệu


12

Vì vậy, tôi đã tạo ra một lớp truy cập dữ liệu thông qua TDD và đã tiếp cận phần nào mối quan tâm. Tôi không muốn bắt đầu đi sai đường, vì vậy tôi nghĩ rằng tôi sẽ hỏi các bạn xem liệu suy nghĩ của tôi có phù hợp với một kiến ​​trúc sạch sẽ không.

Các phương thức trong Lớp truy cập dữ liệu của tôi (viết tắt là DAL), khá đơn giản. Chúng phù hợp với các thủ tục được lưu trữ trong cơ sở dữ liệu (không có cách nào khác để gọi vào đó để giữ mọi thứ sạch sẽ) và chúng chứa các tham số tương tự mà các thủ tục thực hiện. Sau đó, họ chỉ cần kết nối với cơ sở dữ liệu và trả về kết quả truy vấn. Đây là một ví dụ:

public int DeleteRecord(int recordId)
{
    recordId.RequireThat("recordId").NotZeroOrLess();

    List<SqlParameter> parameters = new List<SqlParameter>();
    parameters.Add(new SqlParameter { ParameterName = "@RecordId", SqlDbType = SqlDbType.Int, Direction = ParameterDirection.Input, Value = recordId});

    return this.ExecuteNonQuery("DeleteRecord", parameters.ToArray());
}

Điều này hoạt động hoàn hảo cho loại phương pháp này bởi vì tôi không làm bất cứ điều gì có ý nghĩa với tập kết quả. Tôi chỉ muốn đảm bảo lệnh hoạt động, vì vậy tôi sẽ trả về kết quả của truy vấn không, đó chỉ là các hàng bị ảnh hưởng và tôi có thể xác minh logic bằng cách sử dụng số đó.

Tuy nhiên, nói trong một phương pháp DAL khác, tôi muốn tải một bản ghi. Quy trình tải của tôi sẽ được thực hiện selectsđối với một loạt các bảng và trả về một bảng DataSet, nhưng tôi đang đấu tranh với việc liệu DAL của tôi có nên tạo Đối tượng kinh doanh trong phương thức hay khôngDataSet , hoặc nếu chính Đối tượng kinh doanh của tôi chỉ nên có một Load()phương thức có được DataSettừ DAL, và sau đó về cơ bản tự điền vào.

Việc thực hiện thông qua DAL sẽ dẫn đến ít logic hơn trong các Đối tượng kinh doanh (mặc dù đây chỉ là logic chọn, nó vẫn logic), nhưng sẽ làm cho DAL chùn bước một chút và khiến nó cảm thấy như nó thực sự đang làm điều gì đó mà nó không nên ' đang làm

các bạn nghĩ sao?


Tại sao bạn không sử dụng Entity Framework?
jfrankcarr

@jfrankcarr - Thành thật mà nói, chủ yếu là vì tôi không quen với nó như tôi nên làm. Tuy nhiên, tôi sẽ cần phải làm lại các bảng của mình và thêm các khóa ngoại thích hợp, v.v. để Entity Framework sẽ nhận ra các mối quan hệ đúng cách. Tuy nhiên, vì tò mò, nếu tôi đang sử dụng nó, tôi sẽ thực hiện tất cả các lựa chọn bằng cách sử dụng khung với chính Đối tượng Kinh doanh hay vẫn sẽ có quyết định đặt các truy vấn LINQ đó ở đâu?

Tôi khuyên bạn nên dành thời gian để tìm hiểu EF. Ban đầu có vẻ hơi nản chí, đặc biệt là khi cố gắng làm cho nó phù hợp với cơ sở dữ liệu hiện có có một số vấn đề thiết kế có sẵn, nhưng nó đáng giá.
jfrankcarr

Bạn cũng có thể xem NHibernate nếu bạn muốn xem xét tùy chọn khác.
Don 01001100

@jfrankcarr - Tôi chắc chắn sẽ xem xét nó, nhưng làm thế nào để nó phù hợp với một ứng dụng truy cập dữ liệu nhiều tầng? Bản thân khung thực thể sẽ được triển khai trong chính DAL, hoặc trong một lớp khác hoặc thậm chí chính các Đối tượng Kinh doanh?

Câu trả lời:


4

DAL của bạn sẽ trả về các đối tượng dữ liệu của bạn

Lý tưởng nhất là DAL của bạn phải là một đối tượng "hộp đen", mà mã ứng dụng của bạn có thể sử dụng để yêu cầu một đối tượng dữ liệu hoặc thao tác với các đối tượng dữ liệu hiện có. Đôi khi, có một lớp khác được đặt giữa DAL và mã ứng dụng được gọi là Repositorylớp phân tách hai lớp, mặc dù điều này không phải lúc nào cũng cần thiết.

Ngoài ra, bạn thường không muốn các đối tượng kinh doanh của mình có thể tự tạo. Điều này có thể gây ra lỗ hổng bảo mật nơi ai đó có thể sử dụng thư viện của bạn và tạo một phiên bản mới của đối tượng của bạn bằng cách gọi .Load(someId)nó và nó hợp nhất hai lớp nên tách biệt hoàn toàn.

Tôi cũng không khuyên bạn nên cung cấp một .Load(DataSet ds)phương thức vì nếu định nghĩa của tập dữ liệu thay đổi, bạn sẽ phải tìm ra các đối tượng dữ liệu sử dụng tập dữ liệu đó và thay đổi chúng. Việc giữ tất cả mã truy cập dữ liệu của bạn ở một nơi dễ dàng hơn, vì vậy nếu bạn thay đổi truy vấn truy cập dữ liệu, bạn chỉ nên thay đổi lớp DAL.


Không chắc chắn làm thế nào một lớp có thể phụ thuộc vào "trả về đúng đối tượng" nếu định nghĩa của "đối tượng đúng" được giữ trong một lớp khác.
TMN

@TMN Đó là từ xấu. Tôi đã thay đổi từ ngữ một chút vì bạn nói đúng, mã ứng dụng sẽ biết loại đối tượng mà nó yêu cầu.
Rachel

@Rachel - Gotcha. Vì vậy, bạn có khuyên DAL trả lại một thể hiện của bất kỳ đối tượng kinh doanh nào của tôi không, đúng không? Tôi hơi bối rối bởi cách diễn đạt của bạn về "đối tượng dữ liệu", nhưng tôi nghĩ tôi hiểu nó. Bằng cách đó, mã của tôi có thể yêu cầu Đối tượng kinh doanh từ bất cứ nơi nào nó cần (không phải thông qua chính họ), chỉ bằng cách gọi BusinessObject bo = DAL.LoadRecord(id);- âm thanh phải không? Logic để ánh xạ truy vấn tới chính BO sẽ được chứa trong DAL và chỉ có ở đó.

1
@Scott Điều đó đúng, mặc dù tôi sẽ đặt tên cho phương thức DAL là một cái gì đó giống như Getthay vì Load, nhưCustomer c = DAL.GetCustomer(id);
Rachel

2

Phương pháp của tôi, ngay cả trước LINQ-To-SQL và Entity Framework, là có một giao diện và thư viện lớp trừu tượng cung cấp một "hợp đồng bằng văn bản" để liên lạc giữa các lớp khác nhau của ứng dụng. Điều này đôi khi được gọi là một bản thể luận , một định nghĩa cho một miền công việc. Bất cứ điều gì đã qua giữa các lớp đều sử dụng 'hợp đồng' này.

Tôi không thích ý tưởng chuyển các đối tượng Dataset thô từ lớp dữ liệu sang lớp nghiệp vụ. Tôi đã thấy kết quả này trong một số vấn đề, đặc biệt là khi tích hợp các nguồn dữ liệu cũ. Nó cũng có thể gây khó khăn cho những người mới tham gia vào một dự án để hiểu dữ liệu đến từ đâu. Cuối cùng, nó yêu cầu lớp doanh nghiệp của bạn phải xử lý dữ liệu trực tiếp từ DB, điều này có thể dẫn đến các biến chứng.

Mã ví dụ mà bạn có trông giống với mã tôi đã có trước LINQ. Tôi đã có một lớp chức năng DB chung mà tôi đã sử dụng bên trong các đối tượng DAL của mình. Các lớp DAL sẽ đọc dữ liệu và điều chỉnh nó vào các đối tượng 'hợp đồng'. Kết quả vô hướng, như ví dụ xóa của bạn, sẽ trả về một giá trị, thường là boolean.


1
"Tôi không thích ý tưởng chuyển các đối tượng Dataset thô từ lớp dữ liệu sang lớp nghiệp vụ." Điều này. Một ngàn lần, điều này.
Joshua Smith

@jfrankcarr - DAL của tôi thực sự thực hiện một giao diện và tôi có kế hoạch có giao diện cho mọi thứ truyền dữ liệu từ lớp này sang lớp khác, vì vậy tôi nghĩ rằng ý tưởng mẫu của chúng tôi phù hợp ở đó. Vì vậy, bạn có khuyên tôi nên thay đổi các phương thức trả về kết quả trực tiếp của các ExecuteScalartruy vấn để trả về các giá trị có ý nghĩa hơn đối với một lớp nghiệp vụ không, chẳng hạn như bool? Tôi nghĩ khác, đây là một câu trả lời rất giống với Rachel.

Tôi thường trả lại một boolean cho các cuộc gọi tạo / cập nhật / xóa trừ khi tôi cần số lượng hồ sơ bị ảnh hưởng. Ví dụ, tôi có thể trả về một int nếu một Proc được lưu trữ đang xử lý nhiều dòng đơn hàng hoặc một cái gì đó tương tự.
jfrankcarr

0

DAL của bạn sẽ trả lại một Dataset. Bộ dữ liệu được trả về phải là đối tượng kinh doanh, không nên có bất cứ điều gì bạn cần làm với nó ngoài việc kiểm tra xem nó có dữ liệu dự kiến ​​hay không. Nếu bạn cần phải làm nhiều hơn với nó thì bạn đang cố gắng làm quá nhiều trong một thủ tục được lưu trữ hoặc không trả lại dữ liệu đúng cách trong thủ tục được lưu trữ.


0

Tôi muốn đề xuất các đối tượng kinh doanh của bạn có một hàm tạo để tự tạo từ tập kết quả. Điều này loại bỏ khớp nối giữa DAL của bạn và lớp doanh nghiệp. Nếu bạn muốn cách ly hoàn toàn cả hai, hãy tạo một bản đồ đơn giản của các tên cột => các cặp giá trị từ tập kết quả của bạn và chuyển nó cho hàm tạo.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.