Önce Kod: Bağımsız dernekler mi Yabancı anahtar dernekler mi?


103

Yeni bir proje üzerinde her çalışmaya başladığımda kendimle zihinsel bir tartışmaya giriyorum ve POCO'larımı tasarlıyorum. Yabancı anahtar ilişkilerini tercih ediyor gibi görünen birçok öğretici / kod örneği gördüm :

Yabancı anahtar ilişkisi

public class Order
{
    public int ID { get; set; }
    public int CustomerID { get; set; } // <-- Customer ID
    ...
}

Bağımsız derneklerin aksine :

Bağımsız dernek

public class Order
{
    public int ID { get; set; }
    public Customer Customer { get; set; } // <-- Customer object
    ...
}

Geçmişte NHibernate ile çalıştım ve yalnızca daha fazla OO hissetmekle kalmayan, aynı zamanda (tembel yüklemeyle) bana sadece kimliği yerine tüm Müşteri nesnesine erişim sağlama avantajına sahip olan bağımsız ilişkilendirmeler kullandım. Bu, örneğin, bir Order örneğini almamı ve ardından Order.Customer.FirstNameaçıkça bir birleştirme yapmak zorunda kalmadan yapmamı sağlıyor, bu da son derece kullanışlı.

Özetlemek gerekirse, sorularım:

  1. Bağımsız dernekleri kullanmanın önemli dezavantajları var mı? ve...
  2. Hiç yoksa, yabancı anahtar ilişkilerinin kullanılmasının nedeni ne olabilir?

Yanıtlar:


106

ORM'den tam olarak yararlanmak istiyorsanız, kesinlikle Varlık referansını kullanacaksınız:

public class Order
{
    public int ID { get; set; }
    public Customer Customer { get; set; } // <-- Customer object
    ...
}

FK'lerle bir veritabanından bir varlık modeli oluşturduğunuzda, her zaman varlık referansları üretecektir. Bunları kullanmak istemiyorsanız EDMX dosyasını manuel olarak değiştirmeli ve FK'leri temsil eden özellikler eklemelisiniz. En azından bu, yalnızca Bağımsız ilişkilendirmelere izin verilen Entity Framework v1'deki durumdu.

Varlık çerçevesi v4, Yabancı anahtar ilişkilendirme adı verilen yeni bir ilişkilendirme türü sunar. Bağımsız ve yabancı anahtar ilişkisi arasındaki en belirgin fark, Order sınıfındadır:

public class Order
{
    public int ID { get; set; }
    public int CustomerId { get; set; }  // <-- Customer ID
    public Customer Customer { get; set; } // <-- Customer object
    ...
}

Gördüğünüz gibi hem FK özelliğine hem de varlık referansına sahipsiniz. İki tür ilişkilendirme arasında daha fazla fark vardır:

Bağımsız dernek

  • İçinde ayrı bir nesne olarak temsil edilir ObjectStateManager. Kendine ait EntityState!
  • Dernek kurarken her zaman kuruluşun her iki ucundan da haklara ihtiyacınız vardır
  • Bu ilişkilendirme, varlık ile aynı şekilde eşleştirilir.

Yabancı anahtar ilişkisi

  • İçinde ayrı bir nesne olarak temsil edilmez ObjectStateManager. Bu nedenle bazı özel kurallara uymanız gerekir.
  • İlişki kurarken, her iki ilişkilendirme ucuna ihtiyacınız yoktur. Ana varlığın alt öğe ve PK'sine sahip olmak yeterlidir ancak PK değeri benzersiz olmalıdır. Bu nedenle, yabancı anahtar ilişkilendirmesini kullanırken, ilişkilerde kullanılan yeni oluşturulan varlıklara geçici benzersiz kimlikler de atamanız gerekir.
  • Bu ilişkilendirme eşlenmez, bunun yerine başvurusal kısıtlamaları tanımlar.

Yabancı anahtar ilişkilendirmesini kullanmak istiyorsanız , Varlık Veri Modeli Sihirbazı'nda modele yabancı anahtar sütunlarını dahil et seçeneğini işaretlemelisiniz .

Düzenle:

Bu iki tür dernek arasındaki farkın çok iyi bilinmediğini fark ettim, bu yüzden bunu daha fazla ayrıntıyla ve bu konudaki kendi fikrimle kapsayan kısa bir makale yazdım .


Çok anlayışlı cevabınız için ve ayrıca konu hakkında bol miktarda kaynak ve her iki tekniğin artıları / eksileri hakkında bana yardımcı olan doğru terminolojiye dikkat ettiğiniz için teşekkürler.
Daniel Liuzzi

1
Makalene az önce rastladım Ladislav. Bu iki yaklaşım arasındaki farkı daha iyi anlamak için çok ilginç okuma ve harika bir kaynak. Şerefe.
Daniel Liuzzi

1
@GaussZ: EF4'ten bu yana derneklerin nasıl ele alınacağı konusunda herhangi bir değişiklik olmadığını bildiğim gibi (FK derneklerinin tanıtıldığı yer).
Ladislav Mrnka

1
Bu ve diğer cevaplar performans endişesini etkilemiyor gibi görünüyor. Ancak, bir MSDN makalesinin Görünüm Oluşturma performansını etkileyen 2.2 faktörleri bölümüne göre , Bağımsız İlişkilendirmenin kullanılması, Dış Anahtar ilişkilendirmelerine göre Görünüm Oluşturma maliyetini artırıyor gibi görünüyor.
Veverke

1
@LadislavMrnka: Yukarıda bahsettiğiniz eserin çalıştığını iki kez kontrol edebilir misiniz? Ben erişemiyorum.
Veverke

34

İkisini de kullan. Ve geç yüklemeye izin vermek için varlık referanslarınızı sanal yapın. Bunun gibi:

public class Order
{
  public int ID { get; set; }
  public int CustomerID { get; set; }
  public virtual Customer Customer { get; set; } // <-- Customer object
  ...
}

Bu, gereksiz DB aramalarından tasarruf sağlar, geç yüklemeye izin verir ve ne olmasını istediğinizi biliyorsanız kimliği kolayca görmenize / ayarlamanıza olanak tanır. Her ikisine de sahip olmanın tablo yapınızı hiçbir şekilde değiştirmediğini unutmayın.


5
Kabul. Ladislav'ın önerdiği gibi, sonunda bunu yapmaya başladım. Size gerçekten her iki dünyanın da en iyisini verir; tüm özelliklerine ihtiyaç duyduğunuzda tüm nesne ve yalnızca PK'ye ihtiyacınız olduğunda ve gerisini umursamadığınızda kimliği.
Daniel Liuzzi

9

Bağımsız ilişkilendirme AddOrUpdate, genellikle Seedyöntemde kullanılanla iyi çalışmaz . Referans mevcut bir öğe olduğunda, yeniden eklenecektir.

// Existing customer.
var customer = new Customer { Id = 1, Name = "edit name" };
db.Set<Customer>().AddOrUpdate(customer);

// New order.
var order = new Order { Id = 1, Customer = customer };
db.Set<Order>().AddOrUpdate(order);

Sonuç, mevcut müşteri yeniden eklenecek ve yeni (yeniden eklenen) müşteri yeni siparişle ilişkilendirilecektir.


Yabancı anahtar ilişkisini kullanıp kimliği atamadığımız sürece.

 // Existing customer.
var customer = new Customer { Id = 1, Name = "edit name" };
db.Set<Customer>().AddOrUpdate(customer);

// New order.
var order = new Order { Id = 1, CustomerId = customer.Id };
db.Set<Order>().AddOrUpdate(order);

Beklenen davranışa sahibiz, mevcut müşteri yeni siparişle ilişkilendirilecek.


2
Bu iyi bir bulgu. Bununla birlikte, bir müşteriyi siparişe bağlamanın çözümü (ve bence doğru yol), onu şu şekilde db bağlamından yüklüyor: var order = new Order { Id = 1, Customer = db.Customers.Find(1) }; Veya müşteriyi db bağlamından yüklemek için Select yöntemini kullanabilirsiniz. Bu, bağımsız dernek ile çalışır.
tala9999

4

Gereksiz aramalardan kaçınmak için nesne yaklaşımını tercih ederim. Özellik nesneleri, tüm varlığı oluşturmak için fabrika yönteminizi çağırdığınızda (yuvalanmış varlıklar için basit geri çağrı kodu kullanarak) aynı şekilde kolayca doldurulabilir. Bellek kullanımı dışında görebildiğim hiçbir dezavantaj yok (ancak nesnelerinizi doğru şekilde önbelleğe alacaksınız?). Yani, yaptığınız tek şey yığını yığın yerine koymak ve arama yapmamaktan bir performans kazancı elde etmektir. Umarım bu mantıklı gelir.

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.