2009-12-18 24 views
5

Giả sử tôi có một tuyên bố một DataTable và DataTable này tôi đã chỉ định một kết quả đó được trở về từ gọi một thủ tục lưu trữ, vì vậy bây giờ, DataTable của tôi chứa một cái gì đó giống như sau khi truy cập vào một hàng từ nó:Có cách nào để không phá vỡ mã nếu các cột trong cơ sở dữ liệu thay đổi không?

string name = dr["firstname"]; 
int age = (int)dr["age"]; 

nếu tên đầu tiên được thay đổi thành first_name và tuổi được xóa, mã rõ ràng sẽ bị hỏng vì bây giờ lược đồ bị hỏng, vậy có cách nào để luôn giữ lược đồ đồng bộ với mã tự động mà không cần thực hiện thủ công không? Có một số loại tệp mô tả meta mô tả các cột trong bảng cơ sở dữ liệu và cập nhật chúng cho phù hợp không? Đây có phải là một trường hợp LINQ có thể hữu ích vì tính chất mạnh mẽ của nó?

Trả lời

9
  1. Điều gì về chế độ xem cũ được chọn theo tên cột, chúng luôn xuất các cột có tên được chỉ định theo thứ tự được chỉ định. Nếu bảng bên dưới cần phải thay đổi, khung nhìn được sửa đổi nếu cần thiết nhưng vẫn xuất ra giống như trước khi bảng thay đổi bên dưới - giống như giao diện cho các đối tượng của bạn. Ứng dụng tham chiếu các khung nhìn thay vì các bảng và tiếp tục hoạt động như bình thường. Điều này dẫn đến thiết kế ứng dụng cơ sở dữ liệu tiêu chuẩn cần được dạy trong bất kỳ khóa học kiến ​​trúc dữ liệu nào (thậm chí cơ bản) - nhưng tôi hiếm khi thấy chúng thực sự được sử dụng trong các ứng dụng nghiệp vụ. Trong thực tế, dự án tôi đang làm là ngày đầu tiên mà tôi đã nhìn thấy cách tiếp cận này được thực hiện và nó làm mới để thực sự nhìn thấy nó được sử dụng đúng cách.

  2. Sử dụng procs được lưu trữ, nếu bảng của bạn thay đổi, sửa đổi proc được lưu trữ sao cho đầu ra vẫn như cũ - được sử dụng theo cách tương tự để che chắn ứng dụng khỏi bảng bên dưới. Không đủ nếu bạn đang muốn thực hiện các phép nối, bộ lọc và tổng hợp động, nơi chế độ xem sẽ phù hợp hơn.

  3. Nếu bạn muốn làm bên ứng dụng, hãy chỉ định tên của các trường bạn đang truy vấn ngay trong truy vấn thay vì sử dụng "select *" và dựa vào tên trường để tồn tại. Tuy nhiên, nếu tên trường trên bảng thay đổi hoặc cột bị xóa, bạn vẫn bị kẹt, bạn phải sửa đổi truy vấn của mình.

  4. Nếu tên của các trường sẽ thay đổi, nhưng tất cả các trường sẽ luôn tồn tại, nội dung của các trường đó sẽ vẫn giữ nguyên và trường sẽ vẫn giữ nguyên, bạn có thể tham chiếu các trường theo chỉ mục thay vì theo tên.

  5. Sử dụng trình ánh xạ quan hệ đối tượng như những người khác đã chỉ định, nhưng tôi không nghĩ điều này nhất thiết phải thiết kế tốt hơn là hy vọng thiết kế khung là đủ tốt và phù hợp với những gì bạn đang làm. không phải là trường hợp. Tôi không thực sự của ý kiến ​​này là một cách tiếp cận tốt mặc dù.

+0

Điểm hay. Câu hỏi: Vì vậy, nếu tôi tạo chế độ xem từ bảng và thay đổi các cột của bảng, chế độ xem sẽ tự động được cập nhật? Trong điểm 4 của bạn, tôi đã nghĩ về điều này, nhưng đây có phải là vấn đề nếu tôi xóa một cột hoặc thay đổi thứ tự? – Xaisoft

+0

@Xaisoft - chế độ xem không tự động cập nhật, nó chỉ là một điểm cách nhiệt. Nếu DBA đang thay đổi tên bảng, họ nên cập nhật chế độ xem tương ứng. Xem xét nó như một hợp đồng, bạn có bảng gốc, và xem có thể giống nhau để bắt đầu. Theo thời gian, bảng được sửa đổi một cách hữu cơ, nhưng Chế độ xem đáp ứng một hợp đồng được xác định trước luôn cung cấp cùng một đầu ra dữ liệu trong cùng một định dạng bất kể cấu trúc bảng bên dưới. – BenAlabaster

+0

ok, tôi hiểu rồi, vì vậy đó là trách nhiệm của DBA. Cảm ơn các đầu vào. – Xaisoft

5

Về cách duy nhất để ngăn chặn điều này là thông qua việc sử dụng các thủ tục lưu trữ mà chọn các cột và đổi tên chúng thành một tên tiêu chuẩn mà được trả lại cho ứng dụng của bạn. Tuy nhiên, điều này sẽ thêm một lớp bảo trì khác vào cơ sở dữ liệu.

+3

Đây không phải là cách duy nhất, lượt xem có thể được sử dụng cho cùng một hiệu ứng che chắn ứng dụng từ các bảng nhưng vẫn cung cấp quyền truy cập vào dữ liệu. – BenAlabaster

+0

Tôi giả sử bạn đang nói về việc sử dụng bí danh khi bạn nói "đổi tên chúng thành tên chuẩn được trả về ứng dụng của bạn" – Xaisoft

+1

Không chính xác. Đây không phải là cách 'duy nhất'. Bạn cũng có thể sử dụng ORM hoặc Views. –

4

Đây là lý do giải pháp ORM như NHibernate được tạo.

Trình tạo mã hoặc trình tạo mã đó dựa trên giản đồ cơ sở dữ liệu.

+0

nHibernate vẫn có thể ngắt nếu thay đổi được thực hiện. ORM hữu ích nhưng không phải là đạn bạc. – gbn

4

Tại sao bạn không muốn thay đổi mã? Nếu tuổi tác bị xóa thì tại sao bạn vẫn muốn lấy nó trong mã của bạn?

Điều Linq làm là cố gắng giữ tất cả logic nghiệp vụ ở một vị trí, mã nguồn, thay vì tách giữa Cơ sở dữ liệu và Mã nguồn.

Bạn nên thay đổi mã khi cột dữ liệu bị xóa.

+0

Có, tôi sẽ loại bỏ nó, nhưng tôi đã tò mò nếu có bất cứ điều gì mà sẽ làm điều đó tự động thay vì phải làm điều đó bằng tay. Nó là tốt cho 1 cột, nhưng khi bạn nhận được vào hàng trăm, nó có thể phát điên. – Xaisoft

0

Có, sử dụng thủ tục lưu trữ cho tất cả truy cập và bí danh tên thuộc tính thực tế trong bảng cho đầu ra cho mã máy khách ... Sau đó, nếu tên cột thực tế trong bảng thay đổi, bạn chỉ cần thay đổi sql trong proc được lưu trữ và để lại bí danh giống như cũ và mã khách hàng có thể giữ nguyên

+0

Ok, tôi nhận được những gì bạn đang nói, nhưng tôi không nói về việc thay đổi tên bảng, tôi đang nói về việc thay đổi tên cột và trong trường hợp điểm của bạn, nếu bản thân tôi hoặc ai đó thay đổi bí danh cho các cột ? – Xaisoft

+0

oh, xin lỗi, tôi không rõ ràng, "tên bảng" tôi có nghĩa là "tên cột trong bảng" - và nếu ai đó cjhanges bí danh, sau đó người khác cần phải thay đổi chúng trở lại ... –

+0

Vì vậy, tôi đoán cuối cùng phải có một số quy trình thủ công – Xaisoft

0

Nó sẽ không giúp khi "tuổi" bị xóa, nhưng nếu bạn biết rằng các cột sẽ luôn được trả về cùng một đơn đặt hàng - ngay cả khi tên thay đổi, thì bạn có thể tham chiếu chúng theo tên cột, thay vào đó, như:

string name = dr[0]; 
int age = (int)dr[1]; 

Tùy thuộc vào phiên bản DB của bạn ld cũng kiểm tra trình tạo truy cập dữ liệu chẳng hạn như SubSonic.

+0

Tôi nhầm lẫn với ví dụ của bạn, nếu tôi đổi tên thành first_name, làm cách nào tôi có thể truy cập nó như dr ["firstname"] như bạn đã chỉ ra? – Xaisoft

+0

@Xaisoft - Anh ấy nói rằng bạn có thể sử dụng vị trí của cột trong resultset. Nếu tên đầu tiên luôn được trả về là cột đầu tiên trong kết quả, bạn có thể nói dr [0] hoặc dr.Columns [0] ... –

+0

Xin lỗi về điều đó. Nebakanezer là đúng - tôi sao chép + dán mã của bạn và sau đó quên thay đổi nó cho ví dụ của tôi. Tôi đã sửa nó ngay bây giờ. – Grinn

2

Dường như bạn phải giới thiệu một lớp trừu tượng khác giữa cơ sở dữ liệu và ứng dụng của bạn. Có, lớp này có thể là Linq2Sql, Entity Framework, NHibernate hoặc bất kỳ khung công tác ORM (mapping relation mapping) nào khác.
Bây giờ về điều đó 'tự động' ... có thể loại thay đổi nhỏ này (đổi tên một cột) có thể được xử lý tự động bởi một số công cụ/khung công tác. Nhưng tôi không nghĩ rằng bất kỳ khung công tác nào cũng có thể đảm bảo việc xử lý các thay đổi một cách tự động. Có nhiều trường hợp bạn sẽ phải tự làm "ánh xạ" giữa cơ sở dữ liệu của bạn và lớp mới đó, để bạn có thể giữ phần còn lại của ứng dụng không bị ảnh hưởng.

4

Như bạn có thể cảm nhận được từ tất cả các câu trả lời được đưa ra, những gì bạn đang tìm kiếm không tồn tại. Lý do cho điều này là bạn nên nhớ các chương trình về cơ bản là các tiến trình xử lý dữ liệu, vì vậy bạn không thể thay đổi dữ liệu của mình mà không thay đổi một thứ gì đó khác trong chương trình. Điều gì sẽ xảy ra nếu nó không phải là tên của cột nhưng loại đó đang thay đổi? Hoặc điều gì sẽ xảy ra nếu cột bị xóa?

Tóm lại, không có giải pháp tốt cho các vấn đề như vậy. Dữ liệu là một phần không thể tách rời của ứng dụng - nếu nó thay đổi, mong đợi ít nhất một số công việc. Tuy nhiên, nếu bạn mong đợi tên thay đổi (ví dụ, cơ sở dữ liệu không phải là của bạn và bạn đã được chủ sở hữu thông báo rằng tên của nó có thể thay đổi trong tương lai) và bạn không muốn triển khai lại ứng dụng vì đó, lựa chọn thay thế để biên dịch lại mã nguồn của bạn đó, như đã nêu trong câu trả lời khác, bao gồm:

  • Sử dụng Stored Procedure
    • bạn có thể sử dụng thủ tục lưu trữ để cung cấp dữ liệu cho ứng dụng. Trong trường hợp thay đổi được đề xuất (đổi tên một cột), DBA hoặc tuy nhiên phụ trách lược đồ cơ sở dữ liệu cũng nên thay đổi thủ tục được lưu trữ.
    • Ưu điểm: Không cần biên dịch lại do sự thay đổi nhỏ trong cơ sở dữ liệu
    • Nhược điểm: Nhiều hiện vật mà trở nên nay là một phần của thiết kế ứng dụng, ứng dụng sự hiểu biết là bị mờ.
  • Sử dụng một Mapping file
    • Bạn có thể tạo một tập tin bản đồ cung cấp cho bạn tên mà ứng dụng của bạn hy vọng một cột nhất định để có và tên thực tế cột có. Như vậy là rất rẻ tiền và dễ dàng.
    • Ưu điểm: Không cần biên dịch lại do sự thay đổi nhỏ trong cơ sở dữ liệu
    • Nhược điểm: thực thể thêm (lớp) trong thiết kế của bạn, ứng dụng sự hiểu biết là bị mờ, bạn cần phải triển khai các tập tin bản đồ về biến đổi .
  • Sử dụng vị trí cột thay cho tên cột
    • Thay vì tham chiếu tên của cột, sử dụng một đối số vị trí (dr [1]).
    • Ưu điểm: Giúp bạn an toàn trước những thay đổi về tên.
    • Nhược điểm: Mọi thứ khác. Nếu bạn thay đổi bảng để chứa dữ liệu hơn (cột mới) có một cơ hội đánh số cột cũng sẽ thay đổi, nếu có của các cột này sẽ bị xóa, bạn cũng sẽ có một vấn đề đánh số vv

Nhưng lời đề nghị. Thay vì truy cập vào cột trực tiếp thông qua một chữ, sử dụng hằng số với một số tiêu chuẩn đặt tên tốt. Vì vậy,

string name = dr["firstname"]; 
int age = (int)dr["age"]; 

trở thành

private const string CUSTOMER_COLUMN_FIRST_NAME = "firstname" 
private const string CUSTOMER_COLUMN_AGE = "AGE" 

string name = dr[CUSTOMER_COLUMN_FIRST_NAME]; 
int age = (int)dr[CUSTOMER_COLUMN_AGE]; 

này không giải quyết được vấn đề của bạn, nhưng nó cho phép bạn thêm ý nghĩa tốt hơn để mã (ngay cả khi bạn quyết định viết tắt tên của hằng số) và làm thay đổi tên dễ dàng hơn, vì nó được tập trung. Và, nếu bạn muốn, Visual Studio có thể tạo ra một lớp (kế thừa từ DataTable) định nghĩa tĩnh các hàng cơ sở dữ liệu của bạn, điều này cũng làm cho ngữ nghĩa mã rõ ràng hơn.

+0

Rất đẹp. Cảm ơn vì những lời khuyên. – Xaisoft

0

Có cách nào để không phá vỡ mã nếu các cột trong cơ sở dữ liệu thay đổi không?

Không

Đó là một điều rất, rất tốt mà bạn không thể làm điều này (hoàn toàn) tự động.

Nếu cơ sở dữ liệu thay đổi sao cho tính năng ứng dụng không còn hợp lệ nữa, bạn không muốn ứng dụng tiếp tục hiển thị đối tượng địa lý nếu cơ sở dữ liệu không còn hỗ trợ tính năng này nữa.

Trong trường hợp tốt nhất, bạn muốn thay đổi cơ sở dữ liệu làm cho mã của bạn không còn biên dịch, vì vậy bạn có thể nắm bắt các vấn đề tại thời gian biên dịch thay vì thời gian chạy. LINQ sẽ giúp bạn nắm bắt các loại vấn đề này tại thời gian biên dịch và có rất nhiều cách khác để tăng sự nhanh nhẹn của cơ sở mã của bạn sao cho các thay đổi cơ sở dữ liệu có thể được truyền đi một cách nhanh chóng thông qua toàn bộ cơ sở mã. Có, ORM có thể trợ giúp về vấn đề này. Trong khi các khung nhìn và các thủ tục lưu sẵn có thể làm cho vấn đề trở nên tốt hơn, chúng cũng có thể làm cho nó tồi tệ hơn bằng cách tăng độ phức tạp và số lượng mã cần phản ứng với các thay đổi đối với các cột trong bảng.

Sử dụng tạo mã của một số loại để tạo (ít nhất một phần nào đó) lớp dữ liệu của bạn là cách tốt nhất để nhận các lỗi thời gian biên dịch khi ứng dụng và cơ sở dữ liệu của bạn không đồng bộ. Bạn cũng nên kiểm tra đơn vị xung quanh lớp dữ liệu của mình để phát hiện càng nhiều mâu thuẫn kiểu thời gian chạy càng tốt khi khó tìm thấy lỗi tại thời gian biên dịch (ví dụ, những thứ như ràng buộc kích thước trên cột).

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