Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoiding repeated projection code in Entity Framework

I'm trying to solve a problem similar to the one described here

Initializing strongly typed objects in LINQ to Entities

only from totally the opposite direction. I have a number of functions in my repository, all of which return identically shaped data. The issue is my projection code:

select new pocoClass
 {
   // complex projection that is several pages long includes grabbing a graph of data
 }

at the moment it exists for each query in the repository. I'd tried moving it into an object initializer, but that gives me the dreaded "Only parameterless constructors and initializers are supported in LINQ to Entities." issue.

I did try splitting into two queries

var candidates = (from thing in _entities.whatever
  where (complex.stuff==true)
  select thing);

var final = (from thing in candidates.AsEnumerable()
  let x = thing.ITEMS.Where(blah=>blah.blah==param)
  let y = x.OTHERITEMS.FirstOrDefault()
  select new pocoClass(thing,x,y);

but here final is always null and the code in new pocoClass is never called. I've included the let x & y in the above because these always vary between each use of the projection.

So, do I have to go back to multiple copies of my projection or is there another way out of this ?

like image 728
Andiih Avatar asked Sep 05 '10 13:09

Andiih


People also ask

What does AsNoTracking do in Entity Framework?

The AsNoTracking() extension method returns a new query and the returned entities will not be cached by the context (DbContext or Object Context). This means that the Entity Framework does not perform any additional processing or storage of the entities that are returned by the query.

When to use as no tracking?

No tracking queries are useful when the results are used in a read-only scenario. They're quicker to execute because there's no need to set up the change tracking information. If you don't need to update the entities retrieved from the database, then a no-tracking query should be used.

What is projection in Entity Framework?

Entity Framework Projection A projection is just a way of mapping one set of properties to another. In Entity Framework, it's a way of translating a full entity (database table) into a C# class with a subset of those properties.


1 Answers

I'm not sure it this is usable for you, but what I often do is create projection methods that take an IQueryable and return an IQueryable to translate from a domain object to a DTO. They look much like this:

public static IQueryable<CustomerDTO> ToCustomerDTO(
    IQueryable<Customer> customers)
{
    return
        from customer in customers
        select new CustomerDTO()
        {
           ...
        };
}

This allows me to have this projection in a single place. From several places in my business layer I call such a method.

There are a few things to note, though:

  • Make sure these projection methods don't contain any business logic. Having any use case specific filters would be bad.
  • Sometimes you have a DTO that contains a complex object graph that you want efficiently pull from the database in a single query. With a bit of creativity this is very often possible, but not when returning an IQueryable. In that case I return an array of DTOs.
  • I place those projection methods as static methods inside the DTO class. While this isn't a very clean design, it found out it makes the code very maintainable.

I hope this helps.

like image 140
Steven Avatar answered Nov 12 '22 07:11

Steven