views:

84

answers:

2

Could anyone advise me on how they've implemented the use of Function Imports when using the Repository pattern against EF 4.0?

We have a table mapped to a Candidate Entity and also a Function Import off an existing sproc that maps to Candidate. This works great in EF but we're abstracting by use of Repositories which take on their constructor the IObjectSet where T is the POCO entity. However this means I'm unable to get a reference to the function import. The only way I can see of doing this is passing a reference to the ObjectContext to the repositories that need it but this feels like a bit of a design smell to me.

Even though several of our Repositories are extended with custom interfaces we're still faced with the same issue.

    public class CandidateRepository : Repository<Candidate>, ICandidateRepository
{
    public CandidateRepository(IObjectSet<Candidate> entities)
        : base(entities)
    {
    }

    public Candidate GetByEmail(string email)
    {
        return Entities.SingleOrDefault(c => c.EmailAddress.Equals(email));
    }

    public bool CandidateExists(string candidateNumber)
    {
        return Entities.SingleOrDefault(c => c.Number.Equals(candidateNumber)) != null;
    }

    public Candidate GetByNumber(string number)
    {
        return Entities.SingleOrDefault(c => c.Number.Equals(number));
    }

    public Candidate GetMember(string number)
    {

        return new Candidate();  //This one needs to return from the Function Import
    }
}

Any advice greatly appreciated.

A: 

To solve your problem directly you can cast entities to ObjectSet<T> and use entites.Context property to get ObjectContext.

public Candidate GetMember(string number)
{
    var objectSet = Enities as ObjectSet<Candidate>;

    if(objectSet == null) throw new Exception("Oh, it's not EF IObjectSet implementation");        

    return objectSet.Context.MyCustomFunction(string number);
}

As you can see this code relies on specific IObjectSet implementation which is not good at all.

The better idea is to create repositories for aggregate roots only rather then for each table. So it will be more natural to pass ObjectContext to repository ctor.

Yury Tarabanko
Thanks for the response Yury. Would you be kind enough to elaborate on your definition of "aggregate roots" please? We're not so far into the development that we couldn't refactor for better extensibility.
Daz Lewis
Well, "aggregate root" is domain driven design (DDD) concept. Consider a simple Order 1..* OrderLine model. Normally you would not create OrderLine without order so you'll need only OrderRepository. Thus Order is an aggregate root holding references to OrderLines. Defining aggregating roots is a practical DDD question which depends on objects your are trying to 'model' in your application.
Yury Tarabanko
A: 

I have went down this route and i have experienced that it is less of a pain when you pass in an interface implementation of the ObjectContext to your repository. The interface implementation should have some way of calling the function. So when you pass in the concrete implementation of the ObjectContext everything should work fine.

zeeshanhirani