Có phải SQL nội tuyến vẫn được phân loại là thông lệ xấu khi chúng ta có Micro ORM không?


26

Đây là một chút của một câu hỏi kết thúc mở nhưng tôi muốn có một số ý kiến, khi tôi lớn lên trong một thế giới nơi các tập lệnh SQL nội tuyến là chuẩn mực, sau đó tất cả chúng tôi đều nhận thức rất rõ về các vấn đề dựa trên nội dung SQL, và sql mong manh như thế nào khi thực hiện các thao tác chuỗi khắp nơi.

Sau đó, đến buổi bình minh của ORM nơi bạn đang giải thích truy vấn về ORM và để nó tự tạo SQL, trong nhiều trường hợp không tối ưu nhưng an toàn và dễ dàng. Một điều tốt nữa về các ORM hoặc các lớp trừu tượng cơ sở dữ liệu là SQL được tạo bằng công cụ cơ sở dữ liệu của nó, vì vậy tôi có thể sử dụng Hibernate / Nhibernate với MSSQL, MYSQL và mã của tôi không bao giờ thay đổi nó chỉ là một chi tiết cấu hình.

Bây giờ nhanh chóng chuyển tiếp đến ngày hôm nay, nơi các Micro ORM dường như đang chiến thắng nhiều nhà phát triển hơn, tôi đã tự hỏi tại sao chúng ta dường như đã thực hiện một U-Turn trên toàn bộ chủ đề sql nội tuyến.

Tôi phải thừa nhận rằng tôi thích ý tưởng không có tệp cấu hình ORM và có thể viết truy vấn của mình theo cách tối ưu hơn nhưng có cảm giác như tôi đang tự mở lại các lỗ hổng cũ như SQL SQL và tôi cũng đang tự buộc mình vào một công cụ cơ sở dữ liệu vì vậy nếu tôi muốn phần mềm của mình hỗ trợ nhiều công cụ cơ sở dữ liệu, tôi sẽ cần thực hiện thêm một số hoạt động hack chuỗi mà dường như sau đó bắt đầu làm cho mã không thể đọc được và dễ vỡ hơn. (Ngay trước khi ai đó đề cập đến nó, tôi biết bạn có thể sử dụng các đối số dựa trên tham số với hầu hết các orms vi mô cung cấp sự bảo vệ trong hầu hết các trường hợp từ tiêm sql)

Vì vậy, ý kiến ​​của mọi người về loại điều này là gì? Tôi đang sử dụng Dapper làm Micro ORM của tôi trong trường hợp này và NHibernate là ORM thông thường của tôi trong kịch bản này, tuy nhiên hầu hết trong mỗi lĩnh vực đều khá giống nhau.

Những gì tôi gọi là sql nội tuyếnlà các chuỗi SQL trong mã nguồn. Đã từng có những cuộc tranh luận về thiết kế đối với các chuỗi SQL trong mã nguồn làm mất đi mục đích cơ bản của logic, đó là lý do tại sao các truy vấn kiểu linq được nhập tĩnh trở nên phổ biến chỉ là 1 ngôn ngữ, nhưng hãy nói C # và Sql trong một trang bạn có Bây giờ có 2 ngôn ngữ xen kẽ trong mã nguồn thô của bạn. Để làm rõ, việc tiêm SQL chỉ là một trong những vấn đề đã biết khi sử dụng chuỗi sql, tôi đã đề cập đến việc bạn có thể ngăn điều này xảy ra với các truy vấn dựa trên tham số, tuy nhiên tôi nhấn mạnh các vấn đề khác khi có các truy vấn SQL ăn sâu vào mã nguồn của bạn, chẳng hạn như thiếu tính trừu tượng của Nhà cung cấp DB cũng như mất bất kỳ mức độ lỗi thời gian biên dịch nào đối với các truy vấn dựa trên chuỗi, đây là tất cả các vấn đề mà chúng tôi đã quản lý để bước bên cạnh bình minh của ORM với chức năng truy vấn cấp cao hơn,

Vì vậy, tôi ít tập trung vào các vấn đề nổi bật riêng lẻ và hơn nữa là bức tranh lớn hơn hiện đang trở nên dễ chấp nhận hơn khi có các chuỗi SQL trực tiếp trong mã nguồn của bạn, vì hầu hết các Micro ORM đều sử dụng cơ chế này.

Đây là một câu hỏi tương tự có một vài quan điểm khác nhau, mặc dù nhiều hơn về sql nội tuyến mà không có bối cảnh micro orm:

/programming/5303746/is-inline-sql-hard-coding


1
Bạn có nghĩ rằng bạn có thể viết lại câu hỏi theo cách mà nó không hỏi ý kiến ​​không? Thăm dò ý kiến ​​không phù hợp với định dạng Hỏi & Đáp của Stack Exchange.

Bạn luôn có thể trừu tượng các truy vấn "Micro ORM" của mình trong một lớp riêng biệt, khi cần thiết, bạn trao đổi các truy vấn đang được thực thi khi bạn thay đổi DBMS.
CodeCaster

chưa từng nghe cụm từ "Micro ORM". bạn có nghĩa là các ORM không cố gắng chiếm lĩnh hoàn toàn SQL, hay nó có gì khác không?
Javier

đừng bận tâm, sau một chút googling, nó dường như là một thứ .net.
Javier

1
@GrandmasterB: Giải thích tại sao trong câu trả lời. Tôi đã bỏ qua khá nhiều vấn đề đó trong câu trả lời của mình, vì tôi tin rằng đó là một câu hỏi về sự đánh đổi.
Robert Harvey

Câu trả lời:


31

Những gì bạn đang mô tả là "SQL nội tuyến" thực sự nên được gọi là "nối chuỗi mà không tham số hóa" và bạn không phải làm điều đó để sử dụng Micro ORM một cách an toàn.

Hãy xem xét ví dụ Dapper này:

string sql = "SELECT * from user_profile WHERE FirstName LIKE @name;";
var result = connection.Query<Profile>(sql, new {name = "%"+name+"%"});

Nó được tham số hóa đầy đủ, mặc dù việc nối chuỗi đang diễn ra. Xem dấu hiệu @?

Hoặc ví dụ này:

var dog = connection.Query<Dog>("select Age = @Age, Id = @Id", 
          new { Age = (int?)null, Id = guid });

tương đương với mã ADO.NET sau đây:

List<Dog> dog = new List<Dog>();
using(var cmd = connection.CreateCommand()) {
    cmd.CommandText = "select Age = @Age, Id = @Id";
    cmd.Parameters.AddWithValue("Age", DBNull.Value);
    cmd.Parameters.AddWithValue("Id", guid);
    using(var reader = cmd.ExecuteReader()) {
        while(reader.Read()) {
            int age = reader.ReadInt32("Age");
            int id = reader.ReadInt32("Id");
            dog.Add(new Dog { Age = age, Id = id });
        }
    }
}

Nếu bạn cần linh hoạt hơn mức này, Dapper cung cấp Mẫu SQL và một AddDynamicParms()hàm. Tất cả SQL tiêm an toàn.

Vậy tại sao lại sử dụng chuỗi SQL ở vị trí đầu tiên?

Chà, vì những lý do tương tự, bạn sẽ sử dụng SQL tùy chỉnh trong bất kỳ ORM nào khác. Có thể ORM là SQL tối ưu hóa tạo mã và bạn cần tối ưu hóa nó. Có lẽ bạn muốn làm một cái gì đó khó thực hiện trong ORM nguyên bản, như UNIONs. Hoặc, có lẽ bạn chỉ muốn tránh sự phức tạp của việc tạo tất cả các lớp proxy đó.

Nếu bạn thực sự không muốn viết một chuỗi SQL cho mọi phương thức CRUD trong Dapper (ai làm?), Bạn có thể sử dụng thư viện này:

https://github.com/ericdc1/Dapper.SimpleCRUD/

Điều đó sẽ giúp bạn có CRUD cực kỳ đơn giản và dễ hiểu, trong khi vẫn mang lại cho bạn sự linh hoạt của các câu lệnh SQL viết tay. Hãy nhớ rằng, ví dụ ADO.NET ở trên là cách mọi người đã làm trước khi ORM xuất hiện; Dapper chỉ là một veneer mỏng trên đó.


Các ví dụ hay, tôi đã đề cập rằng bạn có thể bỏ qua việc tiêm SQL thông qua các tham số, vì đây chỉ là một phần của câu hỏi lớn hơn, cũng đã thêm một chỉnh sửa làm rõ ý nghĩa của tôi khi tôi sử dụng thuật ngữ sql nội tuyến .
Grofit

Tôi đã thêm một số chi tiết vào câu trả lời của tôi.
Robert Harvey

2
+1 cho thông tin trên SimpleCRUD không biết điều này tồn tại.
Grofit

Trong Java, bạn sẽ tìm thấy Mybatis khác hơn Hibernate hoặc EclipseLink và. Cách đi của nó là bằng các câu được xác định trước trong XML (thay vì mã hóa trên mã). Nó cũng thêm một số tính năng thú vị làm tiền đề để tăng cường SQL cuối cùng. Gần đây chúng tôi đã sử dụng một web API có tính đồng thời khá cao và một doanh nghiệp không phức tạp và nó hoạt động rất tốt.
Laiv

2

Tôi yêu sql và không thể thấy nó bị băm nhỏ theo chuỗi ký tự, vì vậy tôi đã viết một phần mở rộng VS nhỏ để cho phép bạn làm việc với các tệp sql thực trong các dự án c #. Chỉnh sửa sql trong tệp riêng của nó cung cấp cho bạn intellisense cho các cột và bảng, xác thực cú pháp, thực hiện kiểm tra, kế hoạch thực hiện và phần còn lại. Khi bạn lưu tệp, tiện ích mở rộng của tôi tạo các lớp bao bọc c #, do đó bạn không bao giờ viết một dòng mã kết nối hoặc mã lệnh hoặc tham số hoặc mã đọc. Tất cả các truy vấn của bạn đều được tham số hóa bởi vì không có cách nào khác và bạn đã tạo các kho lưu trữ và POCO để kiểm tra đơn vị, với intellisense cho các tham số đầu vào và kết quả của bạn.

Và tôi đã ném những con dao bít tết miễn phí ... Khi một chuyên gia cần đến và làm lại sql của nhà phát triển của bạn, cô ấy đang xem một tệp sql thực sự và không cần phải chạm vào bất kỳ C # nào. Khi cô ấy quay lại và dọn dẹp DB, xóa một số cột, các tham chiếu đến các cột bị thiếu nhảy thẳng ra là lỗi biên dịch trong c #. Cơ sở dữ liệu trở nên giống như một dự án khác trong giải pháp của bạn mà bạn có thể xâm nhập vào, đó là giao diện có thể tìm thấy trong mã. Nếu giải pháp biên dịch, bạn biết rằng tất cả các truy vấn của bạn đang hoạt động. Không có lỗi thời gian chạy do phôi không hợp lệ hoặc tên cột không hợp lệ hoặc truy vấn không hợp lệ.

Nhìn lại dapper, thứ mà chúng ta vẫn đang sử dụng tại nơi làm việc, tôi không thể tin rằng năm 2016 đây là điều tuyệt vời nhất trong việc truy cập dữ liệu. Thời gian chạy msil là tất cả thông minh, nhưng tất cả các lỗi là lỗi thời gian chạy và thao tác chuỗi, như thao tác chuỗi cho bất kỳ mục đích nào khác, rất tốn thời gian, dễ bị hỏng và dễ bị lỗi. Và làm thế nào có thể khô để lặp lại tên cột trong POCO của bạn, mà bạn phải viết và duy trì bằng tay.

Vì vậy, có bạn đi. Nếu bạn muốn xem xét một công nghệ truy cập dữ liệu chưa được biết đến từ một nhà phát triển chưa từng làm việc trong thời gian rảnh rỗi (với một đứa trẻ và rất nhiều sở thích khác), thì đó là ở đây .


Bạn dường như nghĩ rất nhiều về "sự đổi mới" nhỏ của mình, nhưng điều này khác biệt như thế nào so với ExecuteStoreQuery hoặc ExecuteStoreCommand trong Entity Framework?
Robert Harvey

Tôi không tham gia vào cuộc tranh luận về EF hay SQL. Điều của tôi là dành cho những người muốn sử dụng SQL. Vì vậy, như một cách để thực thi SQL, ExecuteStoreQuery () sẽ điền vào POCO của bạn cho bạn, nhưng bạn vẫn cần xác định POCO của mình, bằng cách nhìn mọi thứ? Và nó không có gì để giúp bạn đặt sql vào một tệp, hoặc tạo các tham số của bạn. Truy vấn của bạn không thể tìm thấy trong mã hoặc có thể kiểm tra được. Xóa các cột sẽ không tạo ra lỗi biên dịch trong ứng dụng của bạn. Tôi có thể tiếp tục, nhưng tôi sợ tôi đang lặp lại chính mình :-) Có lẽ bạn có thể mất 3 phút để xem video youtube. Đó là tiếng Pháp, hãy tắt âm thanh! Tiếng Anh sắp tới.
bbsimonbb

EF hoàn toàn có khả năng tự động tạo ra tất cả các POCO. Tôi đang thiếu gì ở đây? Sự đổi mới thực sự của Dapper và Massive là bạn hoàn toàn không cần POCO; bạn chỉ có thể sử dụng dynamic.
Robert Harvey

Tôi gần như không biết gì về EF. ExecuteStoreQuery () sẽ điền vào một thực thể. Nó sẽ tạo ra một thực thể từ truy vấn . Các thực thể được tạo từ các đối tượng DB (hoặc ngược lại), không phải từ các truy vấn. Nếu truy vấn của bạn không tương ứng với một thực thể hiện có, bạn phải viết POCO của bạn, không?
bbsimonbb

1
:-) phải nói rằng tôi rất nhạy cảm với các khoản phí quảng cáo khi tôi đưa ý tưởng tốt nhất của mình ra khỏi đó một cách tự do. Đây là chút mới nhất của tôi về chủ nghĩa thương mại tích cực. Đến mốc 3 phút, bạn sẽ biết liệu tôi có đang làm gì đó hay không.
bbsimonbb

1

Các truy vấn được tham số hóa cũng như mẫu thiết kế kho lưu trữ cung cấp cho bạn toàn quyền kiểm soát những gì đi vào truy vấn để ngăn chặn các cuộc tấn công tiêm chích. SQL nội tuyến trong trường hợp này không phải là vấn đề ngoài khả năng đọc đối với các truy vấn lớn và phức tạp, dù sao cũng nên có trong các thủ tục được lưu trữ.

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.