简体   繁体   中英

Slow join query - Entity Framework

I'm trying to perform a simple query in Entity Framework.

I have a list of funky things

List<FunkyThing> funkyThings;

Which has 1-5 unique FunkyThing 's in it.

FunkyThing
{
   string FunkyThingUniqueCustomerCode{get;set}
   string UsefullInfoRegardFunkyThings{get;set}
}

I'm trying to do a join onto the funky things table in my database.

The table looks something along the lines of:

FunkyThingsTable

int ID
string UniqueCustomerCode 
string colour
string usefulInfoOfGreatValue
decimal cost

Now as it so happens there's approximately 300,000 funky things in this table.

What I was hoping to do is join my list on to my table to get the usefulInfoOfGreatValue element out. As follows:

var listOfFunkyThingsUsefulInfoQuery = from funkyThing in funkyThings
                                   join
                                      funkyThingDBEntity in unitOfWork.FunkyThingsRepository.Get()
                                      on funkyThing.FunkyThingUniqueCustomerCode equals funkyThingDBEntity .UniqueCustomerCode

                                  select new
                                  {
                                      uniqueCode= funkyThingDBEntity .UniqueCustomerCode,
                                      usefulInfoOfGreatValue= funkyThingDBEntity .usefulInfoOfGreatValue
                                  };

Unfortunately the query takes about 5 seconds to run -even with just one item in the list. What am I doing wrong?

A few quick notes. I'm using the unit of work pattern as described here: http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

The customers for long technical reasons don't have the integer ID, only a string customer code - hence this comparison.

Additional Notes: As per the unit of work article the unitOfWork.FunkyThingsRepository.Get() returns an IEnumerable:

 public virtual IEnumerable<TEntity> Get

I've just tried re-working so use lambda as follows:

var listOfFunkyThingsUsefulInfoQuery = unitOfWork.FunkyThingsRepository.Get().Join (funkyThings, funkyThingDBEntity=>funkyThingDBEntity.UniqueCustomerCode, funkyThings=>funkyThings.FunkyThingUniqueCustomerCode ,(funkyThings,funkyThingDBEntity)=>new {uniqueCode= funkyThingDBEntity .UniqueCustomerCode, usefulInfoOfGreatValue=funkyThingDBEntity .usefulInfoOfGreatValue}) ; 

However sadly this takes the same amount of time

Your query will cause all 300,000 rows be retrieved from the database to memory and perform the join there. Looking at your query, all you're trying to do is extract UsefulInfoOfGreatValue associated with the items in funkyThings based on UniqueCustomerCode .

In the article, the Get() method has a filter parameter that defaults to null. You can set this filter to make your query much faster (ie only get the rows you need)

Try this

var funkyThingsCustomerCodes = funkyThings.Select(x => x.FunkyThingUniqueCustomerCode).ToList();

var listOfFunkyThingsUsefulInfoQuery =
      from funkyThing in unitOfWork.FunkyThingsRepository.Get(e => funkyThingsCustomerCodes.Contains(e.UniqueCustomerCode))
      select new {
        UniqueCode = funkyThing.UniqueCustomerCode,
        UsefulInfoOfGreatValue = funkyThing.UsefulInfoOfGreatValue
      };

Also if you create an index on UniqueCustomerCode column in your table the above query will be even much faster.

try to use eager loading, and use include statement. It will be little faster. Please go through below links, it might help you.

http://msdn.microsoft.com/en-us/data/jj574232.aspx http://blogs.msdn.com/b/adonet/archive/2008/10/07/migrating-from-linq-to-sql-to-entity-framework-eager-loading.aspx

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM