Gup3rSuR4c
Gup3rSuR4c

Reputation: 9490

How to query EF through the PK when using a generic class?

I'm trying to implement a generic class that will interact with a generic repository, and all is fine except for when I have to deal with getting objects out of the repository.

I'm going to have a virtual method in the generic class which will receive an int and I want to use that int to form a query to the repository that gets objects by their primary key. I have a feeling I need to work with the EntityKey property in EF, but not too sure how.

Anyway, here's what I'm trying to do in code, I hope someone will have suggestions on how to accomplish what I want:

public virtual T Get(int PrimaryKey) {
    this.Repository.Select(
        t =>
            (t.PRIMARYKEY == PrimaryKey)).Single();
}

I want to extend this class with more specialized classes, but since most of them only get their objects by querying the PK, it makes since to me to have a base method that can do it.

Thanks in advance for any suggestions!

UPDATE

So, here's where I've gotten with reflection, and I doubt its the proper way, but it somewhat works... I'm getting a NotSupportedException with the message LINQ to Entities does not recognize the method 'System.Object GetValue(System.Object, System.Object[])' method, and this method cannot be translated into a store expression.. Although I understand what it says and why it's saying, I'm not sure how to overcome it when my code looks like this:

private readonly string TEntityName = typeof(T).Name;

public virtual T Get(
    int PrimaryKey) {
    return this.Repository.Select(
        t =>
            (((int)t.GetType().GetProperties().Single(
                p =>
                    (p.Name == (this.TEntityName + "Id"))).GetValue(t, null)) == PrimaryKey)).Single();
}

Hoping that someone who knows how to use reflection, unlike me, can point me in the right direction. Thanks!

Upvotes: 0

Views: 320

Answers (2)

RPM1984
RPM1984

Reputation: 73112

Retrieving an entity by a PK using EF requires an expression/predicate, like this:

Expression<Func<Order,bool>> predicate = x => x.OrderId == 1;
return ctx.Orders.Single(predicate);

There is no easy way (short of reflection or expression tree creation) to be able to dynamically create this predicate.

What you could do is accept the predicate as a parameter:

public virtual T Get(Expression<Func<T,bool>> predicate) {
    this.Repository.Select(predicate).Single();
}

Also make sure you put some generic constraints on T (either at the class/method level).

Upvotes: 1

Tomas Voracek
Tomas Voracek

Reputation: 5914

http://msdn.microsoft.com/en-us/library/bb738961.aspx is way to go. Then use http://msdn.microsoft.com/en-us/library/bb738607.aspx, spend some time in debugger and your misson is completed.

Upvotes: 0

Related Questions