Using CreateSourceQuery in CTP4 Code First

I suppose this is not possible, but I will throw it away anyway. Can I use CreateSourceQuery when programming with the EF4 CodeFirst API in CTP4? I would like to download properties related to a set of properties, for example:

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

But of course, CreateSourceQuery is defined in EntityCollection<T> , while CodeFirst uses a plain old ICollection (obviously). Is there any way to convert?

I got below to work, but this is not quite what I am looking for. Does anyone know how to move from what is lower to what is higher (the code below refers to the class that inherits DbContext)?

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

Thanks!

EDIT: here is my version of the solution sent by zeeshanhirani - who, incidentally, is studying great!

 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:

Ok, I just realized that you cannot send extension methods when using dynamic. Therefore, I think that we are not as dynamic as Ruby, but the above example is easily modified to meet this limitation.

EDIT3:

As mentioned in a blog post by zeeshanhirani, this only works if (and only if) you have shift-enabled permissions that will be created if all of your properties are declared virtual. Here is another version of how a method might look like using CreateSourceQuery with 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
entity-framework-4
source share
2 answers

It is possible. If you checked the collection property with the virtual , then at run time the specific type for EntityCollection will be EntityCollection , which supports CreateSourceQuery and all the useful properties that come with the default code generator. This is how I do it.

 public class Invoice { public virtual ICollection PropertyInvoices{get;set} } dynamic invoice = this.Invoice; dynamic invoice = invoice.PropertyInvoices.CreateSourceQuery().Include("Property"); 

I wrote a blog post about something similar. Just keep in mind that you should not rely on the internal implementation of ICollection converted to EntityCollection . below is a blog post you may find useful

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

+3
source share

You can add a method to the displayed context, which creates the original request for this navigation on the entity instance. To do this, you need to use the base ObjectContext, which includes a relationship manager that provides basic collections of entities / links for each navigation:

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

You can get fancy and accept Func for the navigation property to avoid having to specify T, but here is how the above function is used:

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

Hope this helps!

~ Rowan

+4
source share

All Articles