RBrowning99
RBrowning99

Reputation: 419

Includes generic type parameters

I'm writing some BLL code to sit on top of Entity framework (DAL classes generated with DBContext but that doesn't matter for this question). Here's one of my routines:

public static Customer Get(int32 CustID, IEnumerable<string> IncludeEntities = null)
{
}

So when I call it I pass a CustID, an optinal list of Entities I want included -such as "Orders", and "OrderDetails":

Customer customer = CustomerBLLRepository.Get("ALFKI", 
     new[] { "Orders", "Orders.Order_Details"});

It works fine but I don't like calling it with a list or array of strings - I'd like to get strong typing so the IDE can assist.

I could receive a list of types by declaring it like this:

public static void GetTest(Int32 CustID, params Type[] IncludeEntities)
{
}

and get the class name as a string for the includes to work, but then the caller has to use typeofs like this:

CustomerRepository.GetTest(123, typeof(Order), typeof(OrderDetails));

which is not the end of the world, but this causes problems because OrderDetails is actually a navigation property from Orders, and the include needs to be called Orders.OrderDetails, and I'd have to have the code poke around to find which entity OrderDetails in the child of and still generate the string.

What I really want is a strongly typed list of entities to pass as includes in the same format EF wants them as includes but I think I am SOL.

Upvotes: 1

Views: 180

Answers (2)

Kieren Johnstone
Kieren Johnstone

Reputation: 42003

Determining which entities to include in the query should not be a task for anything other than the BLL. If the BLL takes a property or multiple properties which refer to the structure of the data store, then you're saying whatever calls the BLL needs to know about the internal structure of the data store. Edit: not being clear enough. It's plain wrong to do this.

IMO you should create a separate method for each use case - otherwise your BLL is just a helper method for the DAL, and has no responsibility to separation of concerns.

It's a major issue with the Entity Framework - MS make it seem as if you should put your queries together at whatever point you like, and use and keep the entities alive wherever you like too. Makes it very difficult to see the light indeed.

Upvotes: 0

phil soady
phil soady

Reputation: 11328

Assuming your EF model has relationships maintained Why not use a Custom Get Routine that takes a Lambda. Based on your sample, you get a "customer" back.

public class RepositoryCustomer: RepositoryBase<Customer> 
...
...
public class RepositoryEntityBase<T>
   public virtual T Get(Expression<Func<T, bool>> predicate)
       return Context.Set<T>.Where(predicate).FirstOrDefault();

You the call the Generic Get routine for Any sets on you context,

var aCustomer = RepositoryCustomer.Get(c=>c.id=="ALFKI" && c.Orders.OrderDetail=="bla")

The Virtual navigation properties are very useful and flexible.

Upvotes: 1

Related Questions