2010-08-03 5 views
7

Bunun imkansız olduğunu tahmin ediyorum, ama yine de oraya atacağım. CTP4'te EF4 CodeFirst API ile programlama yaparken CreateSourceQuery kullanmak mümkün mü? Böyle, bir özellik koleksiyonu bağlı yük özelliklerini heyecanla istiyorum:CTP4 Kodunda CreateSourceQuery'yi Kullanma İlk

var sourceQuery = this.CurrentInvoice.PropertyInvoices.CreateSourceQuery(); 
sourceQuery.Include("Property").ToList(); 

Ama tabii CreateSourceQuery EntityCollection<T> tanımlanır, CodeFirst eski ICollection (besbelli) düz kullanır oysa. Dönüştürmenin bir yolu var mı?

Çalışmak için aşağıdakileri aldım, ama aradığım şey tam olarak değil. Herkes, neyin altında olduğuyla yukarıdan ne yapacağını bilir (aşağıdaki kod DbContext'i devralan bir sınıftan gelir)?

ObjectSet<Person> OSPeople = base.ObjectContext.CreateObjectSet<Person>(); 
OSPeople.Include(Pinner => Pinner.Books).ToList(); 

Teşekkürler!

DÜZENLEME: işte zeeshanhirani tarafından gönderilen çözümün sürümüne bakıyorum - yolun kim olduğu şaşırtıcı!

dynamic result; 

if (invoice.PropertyInvoices is EntityCollection<PropertyInvoice>) 
    result = (invoices.PropertyInvoices as EntityCollection<PropertyInvoice>).CreateSourceQuery().Yadda.Yadda.Yadda 
else 
    //must be a unit test! 
    result = invoices.PropertyInvoices; 

return result.ToList(); 

EDIT2:

Tamam, ben sadece dinamik kullanarak ederken uzatma yöntemleri dağıtamazsınız fark etti. Bu yüzden biz Ruby olarak oldukça gibi dinamik değiliz sanırım, ama yukarıdaki örnekte, bu kısıtlama uydurmak için kolayca değiştirilebilir olduğunu

EDIT3:

zeeshanhirani blog yayında belirttiğimiz gibi

, bu sadece çalışır eğer (ve Yalnızca, eğer tüm tüm özelliklerinin sanal olarak bildirilmiş olması durumunda oluşturulacak değiştirmeli vekilleriniz varsa. İşte yöntem Poços

ile
public class Person { 
    public virtual int ID { get; set; } 
    public virtual string FName { get; set; } 
    public virtual string LName { get; set; } 
    public virtual double Weight { get; set; } 
    public virtual ICollection<Book> Books { get; set; } 
} 

public class Book { 
    public virtual int ID { get; set; } 
    public virtual string Title { get; set; } 
    public virtual int Pages { get; set; } 
    public virtual int OwnerID { get; set; } 
    public virtual ICollection<Genre> Genres { get; set; } 
    public virtual Person Owner { get; set; } 
} 

public class Genre { 
    public virtual int ID { get; set; } 
    public virtual string Name { get; set; } 
    public virtual Genre ParentGenre { get; set; } 
    public virtual ICollection<Book> Books { get; set; } 
} 

public class BookContext : DbContext { 
    public void PrimeBooksCollectionToIncludeGenres(Person P) { 
     if (P.Books is EntityCollection<Book>) 
      (P.Books as EntityCollection<Book>).CreateSourceQuery().Include(b => b.Genres).ToList(); 
    } 
+1

Gerçek türüne bakın ('ICollection' uygular). Oyun oynayabilecek misiniz? –

+0

Evet, tamam, her şey yolunda. –

cevap

3

Bunu yapmak için kesinlikle mümkündür CreateSourceQuery kullanmak nasıl görünebileceğini başka versiyonu. virtual anahtar sözcüğüyle size ait toplama özelliğini işaretlediyseniz, çalışma zamanında ICollection için gerçek beton türü CreateSourceQuery ve varsayılan kod üreticisi ile gelen tüm güzellikler için EntityCollection olacaktır. İşte nasıl yapacağım.

public class Invoice 
{ 
    public virtual ICollection PropertyInvoices{get;set} 
} 

dynamic invoice = this.Invoice; 
dynamic invoice = invoice.PropertyInvoices.CreateSourceQuery().Include("Property"); 

Benzer bir şeye blog yazmıştım. Sadece, 'un EntityCollection'a dönüştürülmesinin iç uygulamasına güvenmenin iyi bir uygulama olmadığını unutmayın. Aşağıdaki Size bir varlık örneğinde verilen bir navigasyon için bir kaynak sorgusu oluşturur türetilmiş bağlamı bir yöntem eklemek mümkündür yararlı

http://weblogs.asp.net/zeeshanhirani/archive/2010/03/24/registering-with-associationchanged-event-on-poco-with-change-tracking-proxy.aspx

+0

Aha - genius! Bunun gibi (DAO yönteminin içinde veya binanızın sorgulandığı her yerde) dinamik sonuç; if (invoice.PropertyInvoices olduğunu EntityCollection ) sonuç = (EntityCollection olarak invoices.PropertyInvoices ). CreateSourceQuery(). Yadda.Yadda.Yadda başka // bir birim test olmalı! sonuç = faturalar.Öğrenç Faturalar; return sonuç.ToList(); –

+0

Yuck - bir cevap olarak bunu daha iyi biçimlendirmeyi al. Hey, başka bir notta - Ben * LOVE * kitabın. Ben sadece bitirdim - parlak! Aferin. –

+0

Teşekkürler. Şimdi bana Amazon hakkında bir inceleme borçlusun. Apress'ten başka para kazanmak için kitapta para kazanmama yardımcı olduğu için, kitabın ikinci versiyonunu yazmamızda bize yardımcı olur. – zeeshanhirani

4

bulabileceği blog yazısı olduğunu.

public ObjectQuery<T> CreateNavigationSourceQuery<T>(object entity, string navigationProperty) 
{ 
    var ose = this.ObjectContext.ObjectStateManager.GetObjectStateEntry(entity); 
    var rm = this.ObjectContext.ObjectStateManager.GetRelationshipManager(entity); 

    var entityType = (EntityType)ose.EntitySet.ElementType; 
    var navigation = entityType.NavigationProperties[navigationProperty]; 

    var relatedEnd = rm.GetRelatedEnd(navigation.RelationshipType.FullName, navigation.ToEndMember.Name); 

    return ((dynamic)relatedEnd).CreateSourceQuery(); 
} 

Sen fantezi olsun ve önlemek için navigasyon özelliği için bir Func kabul edebileceğini: Her navigasyon için temel varlık koleksiyonları/referanslar gösterir bir ilişki yöneticisi içerir yatan ObjectContext faydalanmak gerekir Bunu yapmak için burada T belirtmek, bunlarla yukarıdaki fonksiyon nasıl kullanıldığını geçerli:

using (var ctx = new ProductCatalog()) 
{ 
    var food = ctx.Categories.Find("FOOD"); 
    var foodsCount = ctx.CreateNavigationSourceQuery<Product>(food, "Products").Count(); 
} 

Umut bu yardımcı olur!

~ Rowan

+0

Vay - yol serin - teşekkürler Rowan, ve StackOverflow'a hoş geldiniz. –