Devlico.Us
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @devlicious

Derik Whittaker

Thoughts on Software Development, .Net, OOP, Design Patterns and all things cool



Linq2Sql - Explicit Construction of Entity Exception

Gotta say, I am kinda flustered right now.  Today I was trying to perform what I thought to be a pretty straight forward Linq2Sql query, but turns out it was not.

Overview

I have a query that joins a few tables together to get some data, but in place of returning explicit instance of a data entity, I wanted to do a select new XXXX.  I wanted to do this because I had extended the main entity to have a extra property that is needed based on my domain.  And because I did NOT want to create a who new entity, I thought this was the path with the least resistance.  WRONG.

Here is what I WANTED to do.

var items = ( from ctl in DBContextInstance().CampaignTrackingLinks
         join cts in DBContextInstance().CampaignTrackingSummaries on ctl.CampaignTrackingSummaryID equals cts.ID
         join ctcts in DBContextInstance().CampaignTrackingClickThroughStats on cts.ID equals ctcts.CampaignTrackingSummaryID
         where cts.SendID == sendID
         where ctl.Url == ctcts.URL
         select new CampaignTrackingLink
         {
             TotalClicks = ctl.TotalClicks,
             UniqueClicks = ctl.UniqueClicks,
             Url = ctl.Url,
             Alias = ctl.Alias
             PercentOfClicks = ctcts.PercentOfClicks
         }
       ).ToList();

However, every time I ran this code I received  the following exception 'Explicit construction of entity type 'XXXXX.CampaignTrackingLink' in query is not allowed.'.  What was throwing me at first was I KNEW that my syntax was correct, but it still did not work.

After a bit of googling I found (here) something that I think may explain why this is happening. 

The solution to get this to work was not to create a new instance of my extended Linq entity, but to create a whole new entity that inherits off of my Linq entity.  For some reason this worked

    public class CampaignTrackingLinkBreakdown : CampaignTrackingLink
    {
        public double PercentOfClicks { get; set; }
    }

It really sucks that I needed to create a new class that inherited off my Linq entity, but you do what you have to get it working.

var items = ( from ctl in DBContextInstance().CampaignTrackingLinks
         join cts in DBContextInstance().CampaignTrackingSummaries on ctl.CampaignTrackingSummaryID equals cts.ID
         join ctcts in DBContextInstance().CampaignTrackingClickThroughStats on cts.ID equals ctcts.CampaignTrackingSummaryID
         where cts.SendID == sendID
         where ctl.Url == ctcts.URL
         select new CampaignTrackingLinkBreakdown
         {
             TotalClicks = ctl.TotalClicks,
             UniqueClicks = ctl.UniqueClicks,
             Url = ctl.Url,
             Alias = ctl.Alias,
             PercentOfClicks = ctcts.PercentOfClicks
         }
       ).ToList();

So as you can see, I get the same end result, but have to jump through a few extra hoops.

Based on the feedback from the forum link above, this issue is due to the fact that Linq attempts to keep track of all entities for change state reasons and allowing for explicit construction via a query could cause a caching issue.  In my situation, I DO NOT care about change state as this is a read only entity so there will be no updates/inserts done later.

Oh well, at least now I know the issue and how to work around it.

If anyone knows of a better/cleaner way to solve this issue, please let me know.

Till next time,


Published Apr 25 2008, 10:38 AM by Derik Whittaker
Filed under:

Comments

Darrell Mozingo said:

I don't think you necessarily have to inherit from the LINQ entity to get this to work, as I load my DTOs in a similar fashion and they're just POCOs.

# April 25, 2008 1:55 PM

Derik Whittaker said:

@Darrell,

You are 100% correct.  In my case I did not even want a POCO.  I only inherited it because i did not want to reinvent that whell.

There are other places where i create a POCO

# April 25, 2008 2:01 PM

Nick said:

What if you set the ObjectTracking property on the DataContext to false?

# April 25, 2008 2:29 PM

Dew Drop - April 26, 2008 | Alvin Ashcraft's Morning Dew said:

Pingback from  Dew Drop - April 26, 2008 | Alvin Ashcraft's Morning Dew

# April 26, 2008 5:29 PM

Josh said:

Hello,  I am trying to do the same thing but return an IQueryable<T>.  It is not working for me though.  Is there anything special I need to do to make that happen?  Is it possible?

<code>

public static IQueryable<Case> GetAll()

{

         var q = from o in db.Cases

                   join c in db.Customers on o.Id equals c.CaseId

                   select new Case

                   {

                    ...

                   };

           return q;

}

</code>

any help would be great.

# June 18, 2008 8:09 PM

Dave McAlister said:

Make sure the entity you want to create has no primary key (in the designer) and then it works just fine.

# October 22, 2008 5:11 AM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Derik Whittaker

Derik is a .Net Developer/Architect specializing in WinForms working out the northern suburbs of Chicago. He is also believer and advocate for Agile development including SCRUM, TDD, CI, etc.

When Derik is not writing code he can be found spending time with his wife and young son, climbing on his bouldering wall, watching sports (mostly baseball), and generally vegging out. Check out Devlicio.us!

Our Sponsors

Red-Gate!