Satır içi SQL hala Micro ORM'lere sahip olduğumuz için hala kötü bir uygulama olarak mı sınıflandırılıyor?


26

Bu biraz açık uçlu bir soru, ancak bazı düşünceler istedim, satır içi SQL betiklerinin norm olduğu bir dünyada büyüdüğümde, hepimiz SQL enjeksiyon temelli sorunların ve sql'nin ne kadar kırılgan olduğunun farkında olduk. her yerde dize manipülasyonları yapıyorum.

Sonra, ORM'nin sorgusunu anlattığınız ORM'nin şafağı geldi ve çoğu durumda optimal olmayan ancak güvenli ve kolay olan kendi SQL'ini yaratmasına izin verdi . ORM'ler veya veritabanı soyutlama katmanları hakkında bir başka iyi şey de SQL'in veritabanı motorunu göz önünde bulundurarak üretilmesiydi, bu yüzden Hibernate / Nhibernate ile MSSQL, MYSQL kullanabildim ve kodum hiçbir zaman bir yapılandırma detayı olmadı.

Şimdi, Micro ORM'lerin daha fazla geliştiriciyi kazandığı görülmekte olan güne hızlı ilerleyin. Neden tüm çevrimiçi sql konusunu neden U-Turn aldığımızı merak ediyordum.

ORM yapılandırma dosyaları olmadığı fikrinden hoşlandığımı ve sorgumu daha optimal bir şekilde yazabildiğimi itiraf etmeliyim ama kendimi SQL enjeksiyonu gibi eski kırılganlıklara geri açıyor gibi hissediyorum ve ayrıca kendime bağlıyorum bir veritabanı motoru, eğer yazılımımın birden fazla veritabanı motorunu desteklemesini istersem, daha sonra kodu okunamayan ve daha kırılgan hale getirmeye başlayacak gibi daha fazla string hackeri yapmam gerekecekti. (Biri bahsetmeden hemen önce, çoğu durumda sql enjeksiyonundan koruma sağlayan çoğu mikroorganizma ile parametre tabanlı argümanları kullanabileceğinizi biliyorum.)

Peki, halklar bu tür şeyler hakkında ne düşünüyor? Bu durumda Dapper'ı buradaki Micro ORM'im ve bu senaryoda da normal ORM'im olarak NHibernate kullanıyorum, ancak her alanda çoğu benzer.

Satır içi sql olarak ne kastediyorumkaynak kod içindeki SQL dizeleridir. Kaynak kodda, mantığın temel amacından uzaklaşan SQL dizeleri üzerinde tasarım tartışmaları vardı, bu nedenle statik olarak yazılan linq stil sorguları hala sadece 1 dilde popüler hale geldi, ancak bir sayfada C # ve Sql diyelim. Artık ham kaynak kodunuzla iç içe geçmiş 2 dil. Sadece açıklığa kavuşturmak için, SQL enjeksiyonu sql dizeleriyle ilgili bilinen sorunlardan sadece bir tanesidir, bunun parametre bazlı sorgularla olmasını engelleyebileceğinizden bahsetmiştim, ancak kaynak kodunuzda SQL sorgularının gömülmesiyle ilgili diğer sorunları vurguladım. DB Satıcısı soyutlama eksikliğinin yanı sıra, dize tabanlı sorgularda yakalanan herhangi bir derleme zamanı hatası seviyesini kaybetmenin yanı sıra, tüm bunlar, ORM'lerin şafağında üst düzey sorgulama işlevleriyle başa çıkmayı başardığımız sorunlardır.

Bu yüzden, tek tek vurgulanan konulara daha az odaklandım ve daha büyük bir resim, çoğu mikro ORM'nin bu mekanizmayı kullanması nedeniyle SQL dizelerinin doğrudan kaynak kodunuzda tekrar kullanılması daha kabul edilebilir hale gelmesidir.

Aşağıda, mikro orm bağlamı olmayan satır içi sql hakkında daha fazla olmasına rağmen, birkaç farklı bakış açısına sahip benzer bir soru var:

https://stackoverflow.com/questions/5303746/is-inline-sql-hard-coding


1
Soruyu bir fikir talep etmeyecek şekilde yeniden ifade edebileceğinizi düşünüyor musunuz? Fikir almak için oylama, Stack Exchange'in Soru ve Cevap formatına tam olarak uymuyor.

"Micro ORM" sorgularınızı her zaman ayrı bir sınıfta özetleyebilirsiniz, gerektiğinde DBMS'nizi değiştirirken yürütülen sorguları değiştirirsiniz.
CodeCaster

"Micro ORM" terimini duymadım. SQL'i tamamen devralmaya çalışmayan ORM'leri mi kastediyorsunuz, yoksa farklı bir şey mi?
Javier,

Sonunda, biraz googling sonra, net bir şey gibi görünüyor.
Javier,

1
@GrandmasterB: Cevabın neden olduğunu açıklayın. Cevabımda bu konuyu çok yakından takip ettim, çünkü bunun bir takas sorunu olduğuna inanıyorum.
Robert Harvey,

Yanıtlar:


31

"Satır İçi SQL" olarak tanımladığınız şeye "parametrelemesiz dize bitiştirme" adı verilmelidir ve bir Micro ORM'yi güvenle kullanmak için bunu yapmanız gerekmez.

Bu Dapper örneğini ele alalım:

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

Dize bitiştirme gerçekleşse bile, tamamen parametrelenmiştir. @ İşaretini gördün mü?

Veya bu örnek:

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

kabaca aşağıdaki ADO.NET koduna eşdeğerdir:

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 });
        }
    }
}

Bundan daha fazla esnekliğe ihtiyacınız varsa, Dapper SQL Şablonları ve bir AddDynamicParms()işlev sunar. Tüm SQL Injection güvenlidir.

Öyleyse neden ilk olarak SQL dizeleri kullanıyorsunuz?

Aynı nedenlerden dolayı, herhangi bir ORM'de özel SQL kullanırsınız. Belki de ORM kod üreten alt optimal SQL'dir ve onu optimize etmeniz gerekir. Belki de UNION'lar gibi doğal olarak ORM'de yapılması zor bir şey yapmak istersiniz. Veya, belki de tüm bu vekil sınıflarını oluşturmanın karmaşıklığından kaçınmak istersiniz.

Gerçekten , Dapper'daki her bir CRUD yöntemi için bir SQL string yazmak istemiyorsanız (kim yapar?), Bu kütüphaneyi kullanabilirsiniz:

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

Bu, size elle yazılmış SQL ifadelerinin esnekliğini verirken son derece basit ve anlaşılır CRUD sağlayacaktır. Unutmayın, yukarıdaki ADO.NET örneği, ORM gelmeden önce herkesin yaptığı yöntemdi; Dapper bunun üzerine sadece ince bir kaplamadır.


İyi örnekler, SQL enjeksiyonunu parametreler yoluyla kaldıramayacağınızdan zaten bahsetmiştim, çünkü bu daha büyük sorunun sadece bir kısmı, satır içi sql terimini kullandığımda ne anlama geldiğimi açıklayan bir düzenleme de ekledi .
Grofit,

Cevabımı biraz detay ekledim.
Robert Harvey

2
SimpleCRUD ile ilgili bilgi için +1, bunun var olduğunu bilmiyordu.
Grofit

Java'da , Hazırda Beklet veya EclipseLink'ten daha ligther olan Mybatis'i bulacaksınız . Gitme yolu XML'de önceden tanımlanmış cümleler kullanmaktır (koda kodlama yerine). Ayrıca, son SQL'i geliştirmek için ön koşullar olarak bazı ilginç özellikler de ekler. Son zamanlarda oldukça yüksek eşzamanlılığı olan ve karmaşık olmayan bir işi olan bir API web'i kullandık ve harika çalıştı.
LAIV

2

Ben sql seviyorum ve dize değişmezleri doğranmış görmek duramadım, bu yüzden c # projeleri gerçek sql dosyaları ile çalışmanıza izin vermek için küçük bir VS uzantısı yazdı. Sql'yi kendi dosyasında düzenlemek size sütunlar ve tablolar, sözdizimi doğrulaması, test yürütme, yürütme planları ve diğer konular hakkında fikir verir. Dosyayı kaydettiğinizde, uzantım c # sarmalayıcı sınıfları oluşturur, böylece hiçbir zaman bir bağlantı kodu satırı, komut kodu veya parametre veya okuyucu kodu yazmazsınız. Sorgularınızın tümü parametrelenmiştir, çünkü başka bir yol yoktur ve giriş parametreleriniz ve sonuçlarınız için akıllıca birimlerle ünite testi için havuzlar ve POCOlar oluşturdunuz.

Ve ücretsiz biftek bıçağı fırlattım ... Bir uzman gelip geliştiricinizin sql'sini elden geçirmek gerektiğinde, gerçek bir sql dosyasına bakıyor ve herhangi bir C # 'ya dokunması gerekmiyor. Geri dönüp DB'yi düzenli hale getirdiğinde, bazı sütunları silmek, eksik sütunlara yapılan referanslar doğrudan c # dosyasında derleme hataları olarak ortaya çıkar. Veri tabanı, çözümünüzün içine girebileceğiniz başka bir proje gibi olur, kodda bulunabilir bir arayüzdür. Çözüm derlenirse, tüm sorularınızın çalıştığını biliyorsunuzdur. Geçersiz yayınlar veya geçersiz sütun adları veya geçersiz sorgular nedeniyle çalışma zamanı hatası yoktur.

Hala işyerinde kullandığımız dapper'a baktığımda, 2016'da bunun veri erişimindeki en harika şey olduğuna inanamıyorum. Çalışma zamanı msil jenerasyonu zekicedir, ancak tüm hatalar çalışma zamanı hatalarıdır ve dize manipülasyonu, başka herhangi bir amaç için dize manipülasyonu gibi zaman alıcı, kırılgan ve hataya açıktır. Ve sütun adlarınızı POCO'nuzda tekrar yazmanız ve elinizde tutmanız gereken Kuru olabilir.

Al işte ozaman, buyur. Boş zamanlarında (küçük bir çocuk ve diğer hobilerle birlikte) çalışmayan, duyulmamış bir geliştiriciden bilinmeyen bir veri erişim teknolojisine bakmak istiyorsanız, burada .


Küçük "inovasyon" unuzun çok fazla olduğunu düşünüyor gibi görünüyorsunuz, ancak bunun Entity Framework'te ExecuteStoreQuery veya ExecuteStoreCommand'den ne kadar farklı olduğu ?
Robert Harvey

EF ya da SQL tartışmasına girmiyorum. Benim işim SQL kullanmak isteyen insanlar içindir. Dolayısıyla, SQL'i çalıştırmanın bir yolu olarak ExecuteStoreQuery (), POCO'larınızı sizin için dolduracaktır, ancak yine de POCO'larınızı, şeylerin görünümüyle tanımlamanız gerekir mi? Ve sql'yi bir dosyaya koymanıza veya parametrelerinizi oluşturmanıza yardımcı olacak hiçbir şey yapmaz. Sorgunuz kodda bulunabilir veya test edilebilir değil. Sütunları silmek, uygulamanızda derleme hataları üretmez. Devam edebilirdim ama korkarım kendimi tekrar ediyorum :-) Belki de youtube videosunu izlemek için 3 dakika sürebilirsin. Fransızca, sesi kapat! İngilizce geliyor
bbsimonbb

EF, tüm POCO'ları otomatik olarak üretme yeteneğine sahiptir. Burada ne özlüyorum? Dapper ve Massive'in asıl yeniliği POCO'lara hiç ihtiyaç duymamanızdır; Sadece kullanabilirsin dynamic.
Robert Harvey

EF hakkında neredeyse hiçbir şey bilmiyorum. ExecuteStoreQuery () bir varlığı doldurur. Bir birimin oluşturulmasına imkân sorgudan . Varlıklar, sorgulardan değil DB nesnelerinden (veya tersi) oluşturulur. Sorgunuz mevcut bir varlık ile uyuşmuyorsa, POCO'nuzu yazmalısınız, hayır?
bbsimonbb

1
:-) en iyi fikrimi serbestçe ortaya koyarken, reklam suçlamalarına karşı duyarlı olduğumu söylemeliyim. İşte benim en agresif ticarileşme olayım 3 dakikalık işarete göre, bir şey yapıp yapmadığımı bilmelisin.
bbsimonbb

1

Parametreli sorguların yanı sıra depo tasarım deseni, enjeksiyon saldırılarını önlemek için sorguya ne gireceği konusunda tam kontrol sağlar. Bu durumda satır içi SQL, yine de saklı yordamlarda olması gereken büyük ve karmaşık sorguların okunabilirliğinden başka bir konu değildir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.