2012-11-19 9 views
7

Entity Framework uygulamasında yeniyim ve varlıkları veritabanından yüklemek için Kod İlkesinin nasıl kullanıldığını öğrenmeye çalışıyorum.Entity Framework Code İlkesindeki ilgili varlıkların döngüsel yüklenmesini nasıl önlerim?

public class AuditEntry 
{ 
    public int AuditEntryID { get; set; } 

    [Required] 
    public string Message { get; set; } 

    // Navigation Properties 
    public int UserID { get; set; } 
    public virtual User User { get; set; } 
} 

Bir DBContext var sadece iki açığa:

public class User 
{ 
    public int UserID { get; set; } 

    [Required] 
    public string Name { get; set; } 

    // Navigation Properties 
    public virtual ICollection<AuditEntry> AuditEntries { get; set; } 
} 

Her kullanıcı basit bir mesaj içeren her hangi denetim girdileri kümesi olabilir:

Benim modelim bir kullanıcı içeriyor tablolar:

public DbSet<User> Users { get; set; } 
public DbSet<AuditEntry> AuditEntries { get; set; } 

ne yapmak istiyorum karmaşa içeren AuditEntry nesnelerin listesini yüklemek olduğunu Kullanıcı Kimliği ve Ad özelliklerini içeren yaş ve ilgili Kullanıcı nesnesi.

List<AuditEntry> auditEntries = db.AuditEntries.ToList(); 

benim navigasyon özellikleri sanal olarak işaretlenir ve ben sonsuz derin nesne grafiği elde, tembel yükleme devre dışı değil Çünkü (her AuditEntry, her AuditEntries listesini içeren bir User nesnesi vardır Bu, AuditEntries'in bir listesini içeren bir Kullanıcı nesnesini içerir.)

Nesneyi serileştirmek istiyorsam (örneğin bir Web API'sinde sonuç olarak göndermek için), bu iyi bir şey değildir.

Tembel yükleme özelliğini kapatmayı denedim (modeldeki gezinme özelliklerinden gelen sanal anahtar sözcükleri kaldırarak veya bunu ekleyerek bunu .Configuration.LazyLoadingEnabled = false; DBContext'ime). Beklendiği gibi, bu kullanıcı null olarak ayarlanmış bir AuditEntry nesnelerinin düz bir listesiyle sonuçlanır.

var auditentries = db.AuditEntries.Include(a => a.User); 

ama bu öncekiyle aynı derin/döngüsel sonucu ortaya çıkarır: tembel yükleme kapalıyken

, ben Kullanıcı şöyle istekli yüke denedim.

Ayrıca geri referansları/navigasyon özelliklerini takip ederek orijinal nesneyi geri yüklemek ve bir döngü oluşturmaksızın bir seviye derinliği nasıl yükleyebilirim (örn. Kullanıcı kimliğini ve adını ekleyin)? (Dahili) Bu üretir

public dynamic GetAuditEntries() 
{ 
    var result = from a in db.AuditEntries 
       select new 
       { 
        a.AuditEntryID, 
        a.Message, 
        User = new 
        { 
         a.User.UserID, 
         a.User.Username 
        } 
       }; 

    return result; 
} 

mantıklı görünüyor aşağıdaki SQL:

+0

'Include' sadece bunu yapmalıdır. User.AuditEntries'in tembel yükleme olmadığından emin misiniz? –

+0

Nesne düzenlendikten sonra nesneyi serileştirirseniz ne olur? –

+0

İlk başta ancak bunun tembel yükleme olduğunu düşünmüyorum - tüm navigasyon özelliklerimden sanal anahtar kelimeyi kaldırıyorum ve tembel yükleme işlemini açık bir şekilde devre dışı bırakmak yardımcı olmaz. Sanırım her iki yöne giden gezinme özelliklerine sahip olduğumu düşünüyorum, ör. Kullanıcının AuditEntries listesi vardır ve AuditEntries, ait olduğu Kullanıcıyı tanımlar. AuditEntries'i sorgulamak ve Kullanıcı bilgilerini eklemek istiyorum, ancak her üst düzey AuditEntry nesnesinin, o Kullanıcı için diğer tüm AuditEntries'in bir listesini içermesini istemiyorum. Neler olduğunu açıklamakta zorlandığım için çok zor! –

cevap

2

çok hack sonra, benim Linq sorguda dinamik dönüş tipi ve projeksiyon kullanılarak aşağıdaki olası çözüm ile geldim

SELECT 
[Extent1].[AuditEntryID] AS [AuditEntryID], 
[Extent1].[Message] AS [Message], 
[Extent1].[UserID] AS [UserID], 
[Extent2].[Username] AS [Username] 
FROM [dbo].[AuditEntries] AS [Extent1] 
INNER JOIN [dbo].[Users] AS [Extent2] ON [Extent1].[UserID] = [Extent2].[UserID] 

Bu Peşinde olduğum sonuçlar üretir, ama biraz uzun (özellikle benim örnek göre anlamlı daha karmaşık olacağını gerçek hayat modelleri için) soluklu görünüyor ve bu performansı üzerindeki etkisini sorgulayan .

Avantajları Bu benim döndürülen nesnenin kesin içeriği konusunda bana büyük bir esneklik verir

  • . Genellikle UI etkileşimi/şablon oluşturma işleminin çoğunu istemci tarafında yaptığım için, kendimi sık sık model nesnelerimin birden çok sürümünü oluşturmak zorunda buluyorum. Kullanıcıların hangi özellikleri görebileceği genellikle belirli bir ayrıntıya ihtiyacım var (ör.Her kullanıcının e-posta adresini bir AJAX isteğindeki düşük-ayrıcalık kullanıcı tarayıcısına göndermek istemiyorum)

  • Nesne çerçevesinin sorguyu akıllıca oluşturmasına ve yalnızca projeye seçtiğim alanları seçmesine izin verir. Örneğin, her üst düzey AuditEntry nesnesinin içinde User.UserID ve User.Username öğelerini görmek istiyorum, ancak User.AuditEntries öğesini görmüyorum.

Dezavantajları

  • benim Web API dönen tip artık kuvvetle yüzden bu API tabanlı kesinlikle yazılı MVC görünümü oluşturmak olamazdı yazıldığında. Bu olduğu gibi, bu benim özel durumum için bir sorun değil. kodu bir sürü neden olabilir/büyük bir kompleks modelinden bu şekilde elle yansıtma

  • işin çok gibi görünüyor ve API hataları tanıtmak potansiyeline sahiptir. Bu dikkatli bir şekilde test edilmelidir.

  • API yöntemi, modelin yapısıyla sıkı bir şekilde eşleşir ve bu, POCO sınıflarıma göre artık tam otomatik olmadığından, modelde yapılan değişikliklerin, bunları yükleyen koda yansıtılması gerekir.

yöntemini dahil?

.Include() yönteminin kullanımı konusunda hala biraz kafam karışık. Bu yöntemin, ilgili varlıklarla birlikte ilgili varlıkların "istekli" olması gerektiğini belirleyeceğini anlıyorum. Bununla birlikte, kılavuz, navigasyon özelliklerinin bir ilişkinin her iki tarafına yerleştirilmesi ve sanal olarak işaretlenmesi gerektiği için, Dahil Etme yönteminin, yararlılık üzerinde önemli bir olumsuz etkiye sahip olan (özellikle serileştirme sırasında) bir döngü oluşturulmasına neden olduğu görülmektedir. . Benim durumumda

"ağaç" gibi küçük görünecektir:

AuditEntry 
    User 
     AuditEntries * n 
      User * n 
       etc 

ben bu yaklaşım, bu şekilde ya da başka bilgilerle de dinamik kullanmanın etkisi hakkında herhangi bir yorum duymak çok ilgi duyarım .

+0

Merhaba Matt Wilson, Paylaşılan bilgiler için teşekkürler. Dbset'in bazı tamamen yazılmamış erişimlerini yapıyorum. kamu T FindEntity ben dairesel referanslar olmadan hepsini eklemeniz gerekir (nesne kimliği, Liste içerir). Bu konuda herhangi bir yardım… –

+0

yerine "yeni {...}" yeni AuditEntry {...} 'yi denediniz mi? Benzer başarılar için benzer bir deseni bazı başarılarla kullanabildim. Görünüşe göre, örnekleri açıkça oluşturduğunuzda, EntityFramework, sonuçların kodu çözülürken hangi sınıfların başlatıldığını önemsemez. – SingleNegationElimination