Использование CreateSourceQuery в коде CTP4 сначала

Я предполагаю, что это невозможно, но я брошу его там так или иначе. Действительно ли возможно использовать CreateSourceQuery при программировании с EF4 CodeFirst API в CTP4? Я хотел бы нетерпеливо загрузить свойства, присоединенные к набору свойств, как это:

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

Но конечно CreateSourceQuery определяется на EntityCollection<T>, тогда как простое использование CodeFirst ICollection (очевидно). Там некоторый путь состоит в том, чтобы преобразовать?

Я заставил ниже работать, но это не совсем, что я ищу. Кто-либо знает, как пойти от того, что ниже к тому, что выше (код ниже от класса, который наследовал DbContext)?

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

Спасибо!

Править: вот моя версия решения, отправленного zeeshanhirani - кто книга по тому, как удивительно!

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:

Хорошо, я просто понял, что Вы не можете диспетчеризировать дополнительные методы при использовании динамичный. Таким образом, я предполагаю, что мы являемся не совсем столь же динамичными как Ruby, но пример выше является легко модифицируемым для соответствия этому ограничению

EDIT3:

Как упомянуто в сообщении в блоге zeeshanhirani, это только работает, если (и только если) у Вас есть поддерживающие изменение прокси, которые будут созданы, если все Ваши свойства будут объявлены виртуальные. Вот другая версия того, на что метод мог бы быть похожим для использования CreateSourceQuery с POCOs

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();
    }
7
задан Adam Rackis 5 August 2010 в 14:26
поделиться

2 ответа

Это определенно возможно сделать. Если вы обозначили свойство коллекции ключевым словом virtual, то во время выполнения, ваш фактический конкретный тип для ICollection будет EntityCollection, который поддерживает CreateSourceQuery и все плюсы, которые поставляются с генератором кода по умолчанию. Вот как бы я это сделал.

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

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

Я писал статью в блоге о чем-то подобном. Только имейте в виду, что не стоит полагаться на внутреннюю реализацию ICollection, преобразованную в EntityCollection. Ниже приведена статья из блога, которая может быть вам полезна

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

3
ответ дан 7 December 2019 в 07:38
поделиться

К производному контексту можно добавить метод, который создает исходный запрос для данной навигации по экземпляру объекта. Для этого вам нужно использовать базовый ObjectContext, который включает диспетчер отношений, который предоставляет базовые коллекции / ссылки сущностей для каждой навигации:

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

Вы можете пофантазировать и принять Func для свойства навигации, чтобы избежать необходимости указывать T , но вот как используется указанная выше функция:

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

Надеюсь, это поможет!

~ Роуэн

4
ответ дан 7 December 2019 в 07:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: