views:

223

answers:

2

I'm trying to create a generic method to use in my base class for my repositories and I'm having an issue. Here's the method...

        public virtual T First(System.Linq.Expressions.Expression<Func<T, bool>> where, List<string> properties)
    {
        IQueryable<T> query = null;
        if (where != null)
        {
            query = _context.CreateQuery<T>(String.Format("[{0}]", typeof(T).Name.ToString())).Where(where);
        }
        else
        {
            query = _context.CreateQuery<T>(String.Format("[{0}]", typeof(T).Name.ToString()));
        }

        foreach (string s in properties)
        {
            query = query.Include(s);
        }

        T _result = (T)query.First();

        return _result;
    }

When I run the code it gives me this error:

'Company' could not be resolved in the current scope or context. Make sure that all referenced variables are in scope, that required schemas are loaded, and that namespaces are referenced correctly. Near escaped identifier, line 1, column 1.

I have an idea on why it's doing this, I just don't know how to fix it. I think it's doing it because my ObjectContext doesn't know about the object "Company" but it does know "Companies". Any ideas on how to fix this??

The error happens on this line:

T _result = (T)query.First();

Thanks!

+2  A: 

Try to use

 query = _context.CreateObjectSet<T>().Where(where);

instead of

 query = _context.CreateQuery<T>(String.Format("[{0}]", typeof(T).Name.ToString())).Where(where);
Yury Tarabanko
This worked. Thanks Yury! Now can you, or someone, explain why this worked?
Dan H
You are welcome. Well, why this work. Introduction of `IObjectSet<T>` and `ObjectSet<T>` is one of the improvements made in efv4. In previous version it was tricky to create a generic repository since you had to know the name of entityset for entity type you were working with. Here is a good example of `Repository<T>` implementation with except one thing: do not pass `Func<T,bool>` as a selector use `Expression<Func<T, bool>>` as you have already done: http://devtalk.dk/2009/06/09/Entity+Framework+40+Beta+1+POCO+ObjectSet+Repository+And+UnitOfWork.aspx
Yury Tarabanko
+1  A: 

Dan, get the entity set name with something like the following:

string entitySetName = context.MetadataWorkspace
                        .GetEntityContainer(context.DefaultContainerName, DataSpace.CSpace)
                        .BaseEntitySets.Where(bes => bes.ElementType.Name == typeof(T).Name).First().Name;

string name = String.Format("{0}.{1}", context.DefaultContainerName, entitySetName);

query = context.CreateQuery<T>(name).Where(where);

Doing this will resolve the proper plural name for the query.

Using Yury's method would be the best option though.

EDIT By the way, you should return FirstOrDefault() instead of First() in case the query returns no entities (it will throw an InvalidOperationException).

TheCloudlessSky
Changed to FirstOrDefault(). Thanks for the help!
Dan H