views:

160

answers:

3

I have a generic repository and when I'm using a DoQuery method to select objects from the database, I need to load some of the related entities in order to not get nulls in the place of the fields that are foreign keys.

The problem is that the repository is generic, so I do not know how many properties need loading or what their names are (unless there's some way of getting them) how can I make it so that all of the foreign keys have their entities loaded while still keeping this repository generic?

Here's the DoQuery method:

    public ObjectQuery<E> DoQuery(ISpecification<E> where)
    {
        ObjectQuery<E> query = (ObjectQuery<E>)_ctx.CreateQuery<E>("[" + typeof(E).Name + "]").Where(where.EvalPredicate);
        return query;
    }

And a link to the original code for the entire repository.

I posted this once before and never got the answer to it but I figure this one is a little bit more relevant since before people were assuming I knew the property names and could do:

.Include("PropertyNameIKnowNeedsToBeLoaded")

Here's the question I posted before hopefully that will provide a little information on where I'm at with this.

Any help is appreciated.

Thanks,
Matt

A: 

You'll have to invert the control by passing into the method the depth that should be fetched to. I'm not familiar enough with the Entity framework with exactly how to do that. You could pass in an integer representing the fetch depth, and the method can figure out how to construct a query with the related entities to that depth.

Jace Rhea
Can anyone give me an example of how to do this? Not quite sure where to start to try this out...
Matt
A: 

You can get the relations ends names for a type and call Include for all relations.

    public ObjectQuery<E> DoQuery<E>(ISpecification<E> where) where E : new()
    {
        ObjectQuery<E> query = (ObjectQuery<E>)_ctx.CreateQuery<E>("[" + typeof(E).Name + "]").Where(where.EvalPredicate);

        IEntityWithRelationships entityWithRelationship = (IEntityWithRelationships)(new E());
        IEnumerable<IRelatedEnd> relatedEnds = entityWithRelationship.RelationshipManager.GetAllRelatedEnds();
        foreach (IRelatedEnd end in relatedEnds)
        {
            query= query.Include(end.TargetRoleName);
        }

        return query;
    }

I added a "new" generic constraint because I need to get an IEntityWithRelationships from the queried type. I hope this helps.

Branislav Abadjimarinov
Gives me a "Constraints are not allowed on non-generic declarations" for "where" in "where E : new()"
Matt
I corrected the example - It has to be DoQuery<E>, not just DoQuery
Branislav Abadjimarinov
A: 

I have solved this problem by the next way:

 public IQueryable<E> GetAll()
        {
            Type et=typeof(E);
            ObjectQuery<E> oq=_context.CreateQuery<E>("[" + typeof(E).Name + "Set]");

            foreach(System.Reflection.PropertyInfo pi in et.GetProperties())
            {
                if (pi.PropertyType.Name.Contains("EntityCollection"))
                        oq=oq.Include(pi.Name);

            }

            return oq.AsQueryable();
        }

but it steel has a problems with dipper relations. So steel thinking about this problem