NHibernate ve LINQ to SQL


117

Her iki teknolojiyi de gerçek dünya projelerinde kullanmamış biri olarak, bu ikisinin birbirini nasıl tamamladığını ve işlevlerinin ne kadar örtüştüğünü bilen var mı acaba?

Yanıtlar:


113

LINQ to SQL, sizi sınıf başına tablo modelini kullanmaya zorlar. Bu kalıbı kullanmanın faydaları, hızlı ve kolay uygulanması ve etki alanınızı mevcut bir veritabanı yapısına dayalı olarak çalıştırmanın çok az çaba gerektirmesidir. Basit uygulamalar için bu tamamen kabul edilebilir (ve çoğu zaman tercih edilir), ancak daha karmaşık uygulamalar için geliştiriciler genellikle bunun yerine alan odaklı bir tasarım modeli kullanmayı önerirler (NHibernate bunu kolaylaştırır).

Sınıf başına tablo modelindeki sorun, veritabanı yapınızın alan tasarımınız üzerinde doğrudan bir etkiye sahip olmasıdır. Örneğin, bir müşterinin birincil adres bilgilerini tutmak için aşağıdaki sütunlara sahip bir Müşteriler tablonuz olduğunu varsayalım:

  • Sokak adresi
  • Kent
  • Durum
  • Zip

Şimdi, müşterinin posta adresi için de sütunlar eklemek istediğinizi varsayalım, böylece aşağıdaki sütunları Müşteriler tablosuna eklersiniz:

  • MailingStreetAddress
  • MailingCity
  • MailingState
  • MailingZip

LINQ to SQL kullanıldığında, etki alanınızdaki Müşteri nesnesi artık bu sekiz sütunun her biri için özelliklere sahip olacaktır. Ancak, etki alanına dayalı bir tasarım modelini izliyor olsaydınız, muhtemelen bir Adres sınıfı oluşturmuş olurdunuz ve Müşteri sınıfınızın biri posta adresi ve diğeri de geçerli adresleri için olmak üzere iki Adres özelliği bulundururdunuz.

Bu basit bir örnek, ancak sınıf başına tablo modelinin nasıl biraz kokulu bir alana yol açabileceğini gösteriyor. Sonunda, size kalmış. Yine, yalnızca temel CRUD (oluşturma, okuma, güncelleme, silme) işlevselliğine ihtiyaç duyan basit uygulamalar için LINQ to SQL, basitlik nedeniyle idealdir. Ama şahsen NHibernate'i kullanmayı seviyorum çünkü daha temiz bir alanı kolaylaştırıyor.

Düzenleme: @lomaxx - Evet, kullandığım örnek basitti ve LINQ to SQL ile iyi çalışacak şekilde optimize edilebilirdi. Noktayı eve götürmeyi mümkün olduğunca basit tutmak istedim. Veritabanı yapınızın etki alanı yapınızı belirlemesinin kötü bir fikir olacağı veya en azından yetersiz OO tasarımına yol açacağı birkaç senaryo var.


4
Linq To SQL kullanarak deponuzun uygulamasını kodlayabilirsiniz, bu çok kullanışlıdır.
Nicolas Dorier

1
ActiveRecord olmadığını düşünüyorum, hatta eşlenmiş sınıflar bazı altyapı mantığını kapsıyor. ActiveRecord kalıbı, Customer.Save () olabilir. L2S, nHibernate'deki Session gibi DataContext sınıfı ile İş Birimi modelini uygular, ancak NH'nin gerçek POCO yaklaşımı vardır.
Hrvoje Hudo

1
@kevin "LINQ to SQL aktif kayıt kalıbını kullanır" Bu doğru değil. ADO.NET'in aktif kayıt kullandığını veya NHibernate'in aktif kayıt kullandığını söylemek gibi. Bunların tümü veri erişim teknolojileridir ve herhangi bir belirli veri erişim modelini zorlamazlar. Ben kişisel olarak linq-to-sql'yi depo modeli ile kullanmayı seviyorum. Doğru, linq-to-sql, NHibernate'in yaptığı gibi karmaşık eşlemeleri desteklemiyor.
liammclennan

1
Bunun yerine veritabanınızı normalleştirmeye ve DAL'nizin SQLMetal gibi araçlar tarafından oluşturulmasına izin vermeye ne dersiniz?
Alex

3
@CoffeeAddict Empedans uyuşmazlığı dayanılamayacak kadar fazlaysa, işte o zaman uygulamanız LINQ to SQL on, imo kullanmak için çok karmaşıktır. Örneğimin kötü kokmasının nedeni, LINQ to SQL kullanımının 2 yerine 8 özellik ile sonuçlanması ve bir Address sınıfını alan işlevleri uygulama veya Address sınıfında yapabileceğiniz rutinleri uygulama gibi şeyler yapma yeteneğinizi kısıtlamasıdır. NHibernate kullandıysanız yapın.
Kevin Pang

26

Şimdiye kadar kaçırılan iki nokta:

  • LINQ to SQL, Oracle veya SqlServer dışında herhangi bir veritabanı ile çalışmaz. Bununla birlikte, üçüncü taraflar Oracle için daha iyi destek sunar, örneğin devArt'ın dotConnect , DbLinq , Mindscape'in LightSpeed ve ALinq . (Bunlarla herhangi bir kişisel deneyimim yok)

  • Linq to NHibernate , Linq'i bir Nhiberate ile kullanmanıza izin verir, bu nedenle kullanmama nedenini ortadan kaldırabilir.

Ayrıca Nhibernate'in yeni akıcı arayüzü, Nhibernate'in eşlemesini yapılandırmayı daha az zahmetli hale getiriyor gibi görünüyor. (Nhibernate'in acı noktalarından birinin kaldırılması)


Güncelleme

Linq to Nhiberate, artık alfa sürümünde olan Nhiberate v3'te daha iyidir . Görünüşe göre Nhiberate v3 bu yılın sonuna doğru gönderilebilir.

Varlık Çerçeve .net 4 itibariyle de gerçek seçenek gibi görünmeye başlıyor.


2
Linq'den NHibernate'e hala çok erken bir aşamadadır. Tam bir uygulama değildir ve muhtemelen üretimde kullanıma hiç hazır değildir.
liammclennan

Yeni LinqConnect 2.0 sürümü, kolaylık sağlamak için Tür Başına Tablo miras desteği, PLINQ desteği ve Toplu Güncellemeler işlevi gibi bazı ek özellikler sunar. ORM Designer (Devart Entity Developer) artık Model First desteğine ve Mapping Synchronization özelliğine sahiptir. Daha fazla detay: devart.com/news/2010/dotconnects600.html
devart

23

@Kevin: Sunduğunuz örnekteki sorunun kötü bir veritabanı tasarımı kullanmanız olduğunu düşünüyorum. Bir müşteri tablosu ve bir adres tablosu oluşturup tabloları normalleştireceğini düşünürdüm. Bunu yaparsanız, önerdiğiniz senaryo için kesinlikle Linq To SQL'i kullanabilirsiniz. Scott Guthrie'nin Linq To SQL kullanımı üzerine harika bir yazı dizisi var, bunlara göz atmanızı şiddetle tavsiye ederim.

Linq ve NHibernate'in birbirlerini tamamladığını söyleyebileceğinizi sanmıyorum, çünkü bu, birlikte kullanılabilecekleri anlamına gelir ve bu mümkün olsa da, birini seçip ona bağlı kalmanız çok daha iyi.

NHibernate, veritabanı tablolarınızı etki alanı nesnelerinizle oldukça esnek bir şekilde eşlemenize olanak tanır. Ayrıca, veritabanını sorgulamak için HBL kullanmanıza da olanak tanır.

Linq to SQL ayrıca etki alanı nesnelerinizi veritabanına eşlemenizi sağlar, ancak veritabanını sorgulamak için Linq sorgu sözdizimini kullanır.

Buradaki temel fark, Linq sorgu sözdiziminin, sorgularınızın geçerli olduğundan emin olmak için derleyici tarafından derleme zamanında kontrol edilmesidir.

Linq ile bilinmesi gereken bazı şeyler, sadece .net 3.x'te mevcut olması ve sadece VS2008'de destekleniyor olmasıdır. NHibernate, 2.0 ve 3.x ve VS2005'te mevcuttur.

NHibernate ile bilinmesi gereken bazı şeyler, etki alanı nesnelerinizi veya eşleme dosyalarını oluşturmamasıdır. Bunu elle yapmanız gerekiyor. Linq
bunu sizin için otomatik olarak yapabilir .


15
Ya diğer uygulamaları desteklediği için değiştiremeyeceğiniz eski bir veritabanı yapısına karşı kod yazıyorsanız? Etki alanı modelinizin zayıf veritabanı tasarımını miras almasını mı yoksa veritabanı yapısından bağımsız olarak değişebilen zengin bir etki alanı modeli mi oluşturmak istiyorsunuz?
Larry Foulkrod

7

Fluent NHibernate, eşleme dosyalarınızı basit kurallara göre oluşturabilir. XML yazma yok ve güçlü bir şekilde yazılmış.

Son zamanlarda, performans nedenleriyle Linq'ten SQL'e NHibernate'e geçmemiz gereken bir proje üzerinde çalıştım. Özellikle L2S'nin nesneleri gerçekleştirme yöntemi NHibernate'in aynısından daha yavaş görünüyor ve değişiklik yönetimi de oldukça yavaş. Ve ihtiyaç duyulmayan belirli senaryolar için değişiklik yönetimini kapatmak zor olabilir.

Varlıklarınızı DataContext ile bağlantısı kesilmiş olarak kullanacaksanız - örneğin WCF senaryolarında - değişiklikleri güncellemek için onları DataContext'e yeniden bağlamada çok fazla sorun yaşayabilirsiniz. NHibernate ile bu konuda hiçbir sorun yaşamadım.

L2S'den özleyeceğim şey, çoğunlukla, varlıkların her iki ucundaki ilişkileri güncel tutan kod üretme. Ama sanırım NHibernate'in bunu orada yapması için bazı araçlar var ...


2
Sadece durum diğerlerinde yazınızı okuyup da atlama geminin düşündüğünü - .ObjectTrackingEnabled = falsesenin üzerinde DataContextyaptığınız değişiklik izleme sorunu çözülmüş olurdu. İş birimi modelini satın aldığınız ve DDD yapmak istemediğiniz sürece, Linq-to-SQL gerçekten bunu sağlar.
mattmc3

" Performans nedenleriyle Linq'ten SQL'e NHibernate'e geçmemiz gerekiyordu " - [Akıcı, daha az değil] NHibernate'i birkaç yıldır kullandım, senin için hissediyorum. Sanırım çoğunlukla aldattık ve gerçek performans baskı noktaları için yerel SQL yazdık. Geçişinizin nasıl gittiğine ve buna değip değmeyeceğine dair bir güncelleme (altı yıl sonra ...) duymak ilginç olurdu.
ruffin

5

"LINQ" ile ne demek istediğini açıklayabilir misin?

LINQ bir veri erişim teknolojisi değildir, yalnızca yerel bir yapı olarak sorgulamayı destekleyen bir dil özelliğidir. Belirli arayüzleri (örneğin IQueryable) destekleyen herhangi bir nesne modelini sorgulayabilir.

Birçok kişi LINQ To SQL'e LINQ olarak başvurur, ancak bu hiç de doğru değildir. Microsoft, .NET 3.5 SP1 ile LINQ To Entities'i piyasaya sürdü. Ek olarak, NHibernate bir LINQ arayüzüne sahiptir, bu nedenle verilerinize ulaşmak için LINQ ve NHibernate'i kullanabilirsiniz.


2

LINQ derken, LINQ to SQL'i kastettiğinizi varsayıyorum çünkü LINQ, kendisiyle ilişkili bir veritabanı "devam ediyor" değildir. Bu sadece SQL gibi görünmesini sağlamak için bir sürü sözdizimi şekeri içeren bir sorgu dilidir.

Temel örneklerde, NHibernate ve LINQ to SQL aynı problemi çözüyor gibi görünüyor. Geçtikten sonra, NHibernate'in gerçekten zengin alan modelleri oluşturmanıza izin veren birçok özelliği desteklediğini kısa sürede fark edeceksiniz. Ayrıca, LINQ to SQL'i kullandığınız gibi NHibernate'i sorgulamak için LINQ kullanmanıza izin veren bir LINQ to NHibernate projesi de vardır.


1

Öncelikle iki farklı şeyi ayıralım: Veritabanı modellemesi verilerle ilgilenirken, nesne modelleme varlıklar ve ilişkilerle ilgilenir.

Linq-SQL avantajı, aktif kayıt nesneleri olarak kullanılabilmeleri için veritabanı şemasından hızlı bir şekilde sınıflar oluşturmaktır (bkz. Aktif kayıt tasarım modeli tanımı).

NHibernate avantajı, nesne modellemeniz ve veritabanı modellemeniz arasında esneklik sağlamaktır. Veritabanı, örneğin performans dikkate alınarak verilerinizi en iyi şekilde yansıtacak şekilde modellenebilir. Nesne modellemeniz, Etki Alanına Dayalı Tasarım gibi bir yaklaşım kullanarak iş kuralının öğelerini en iyi şekilde yansıtır. (Kevin Pang yorumuna bakın)

Zayıf modelleme ve / veya adlandırma kurallarına sahip eski veritabanlarında, Linq-to-SQL bu istenmeyen yapıları ve isimleri sınıflarınıza yansıtacaktır. Ancak NHibernate, bu karışıklığı veri eşleştiricilerle gizleyebilir.

Veritabanlarının iyi bir adlandırma ve düşük karmaşıklığa sahip olduğu sıfırdan projelerde, Linq-to-SQL iyi bir seçim olabilir.

Ancak, aynı amaç için otomatik eşlemelerle Fluent NHibernate'i kural olarak haritalama ile kullanabilirsiniz. Bu durumda, XML veya C # içeren herhangi bir veri eşleştiricisi hakkında endişelenmezsiniz ve NHibernate'in, özelleştirebileceğiniz bir kurala dayalı olarak varlıklarınızdan veritabanı şeması oluşturmasına izin verirsiniz.

Öte yandan, Linq-to-SQL öğrenme eğrisi NHibernate'ten daha küçüktür.


0

Veya Castle ActiveRecords projesini kullanabilirsiniz. Eski bir proje için yeni bir kod geliştirmek için kısa bir süredir kullanıyorum. NHibernate kullanıyor ve aktif kayıt kalıbı üzerinde çalışıyor (bildiğim adı verilen şaşırtıcı). Denemedim, ancak bir kez kullandıktan sonra, doğrudan NHibernate desteğine geçme ihtiyacı hissederseniz, projenizin bir kısmı veya tamamı için bunu yapmak çok fazla olmaz.


0

Siz "ikisini de kullanmamış bir kişi için" yazdığınız gibi LINQ to SQL'in kullanımı kolaydır, bu nedenle herkes onu kolayca kullanabilir. Ayrıca çoğu zaman yardımcı olan prosedürleri de destekler. Birden fazla tablodan veri almak istediğinizi varsayalım, ardından bir prosedür yazıp bu prosedürü tasarımcıya sürükleyin ve sizin için her şeyi oluşturacaktır. Prosedür adınızın "CUSTOMER_ORDER_LINEITEM" olduğunu ve bu üç tablodan da kayıt aldığını varsayalım, sonra sadece yazın

MyDataContext db = new MyDataContext();
List<CUSTOMER_ORDER_LINEITEMResult> records = db.CUSTOMER_ORDER_LINEITEM(pram1, param2 ...).ToList<CUSTOMER_ORDER_LINEITEMResult>();

NHibernate tarafından desteklenmeyen foreach döngüsünde kayıt nesnenizi de kullanabilirsiniz

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.