Reputation: 11
I am running into a very odd error with EF6. I have uploaded ~38K records on my first pass. Then on my second round, I query the table with a conditional linq statement. That line of code takes about 4 mins to run. This are my entities.
[Table("RAW_ADWORDS")]
public class AdWord
{
[Key]
public int ID { get; set; }
public bool Processed { get; set; }
public string Client { get; set; }
public long ClientID { get; set; }
public bool Active { get; set; }
public bool ProcessedAllFile { get; set; }
public DateTime LastTimeRun{ get; set; }
public DateTime? LastDateTimeProcessed { get; set; }
public virtual List<AdWordCampaign> Campaigns { get; set; }
}
[Table("foobar")]
public class AdWordCampaign
{
[Key]
public int ID { get; set; }
public string Campaign { get; set; }
public long CampaignID { get; set; }
public string Day { get; set; }
public long Clicks { get; set; }
public string CampaignStatus { get; set; }
public long Cost { get; set; }
public long Impressions { get; set; }
public double CTR { get; set; }
public long AvgCPC { get; set; }
public double AvgPosition { get; set; }
public DateTime DownloadDate { get; set; }
}
}
First I run this:
AdWord objAdWord = adwordsContext.AdWords.Where(c => c.ClientID == iCampaignID).FirstOrDefault();
Then
AdWordCampaign objAdWordCampaign = objAdWord.Campaigns.Where(c => c.CampaignID == iElementCampaignID && c.Day == sElementDate).FirstOrDefault();
The line above seems to load ALL the records first before it does the query. Also it still takes 4 mins if I add a Take(5) in the query.
Upvotes: 1
Views: 197
Reputation: 3373
I've seen this before with EF when referencing linked objects through a "primary object" - i.e. when you do
AdWordCampaign objAdWordCampaign = objAdWord.Campaigns.Where(...).FirstOrDefault();
.
Quite simply it iterates all records one-by-one - and hence the slow query.
If you change to the following, you should get an almost instant response:
AdWord objAdWord = adwordsContext.AdWords.Where(c => c.ClientID == iCampaignID).FirstOrDefault();
AdWordCampaign objAdWordCampaign = <adwordsContext>.Campaigns
.Where(c => <c.AdwordId = objAdWord.Id> && c.CampaignID == iElementCampaignID && c.Day == sElementDate)
.FirstOrDefault();
I've put changes in angular brackets and I'm not sure which property within an AdWordCampaign marks the Id of the AdWord for the relationship from a glance at your model, but I'm sure you get the idea - go direct to Capaigns table via the context, using the AdWord as an addiitonal Where
clause, rather than via the AdWord's Campaigns collection.
Upvotes: 0
Reputation: 8614
You need to watch the queries that are generated & executed on the server and make sure they're optimized.
If you're using MS SQL Server, you want to run the SQL Server Profiler tool. Put breakpoints in your code before you call the method that executes the query. Clear the profiler's display, then execute the method. You can capture the SQL from there, then put it into SSMS and view the plan. If the query doesn't use indexes, you need to add indexes that it will use the next time it runs.
I've only ever used Database First, not Code First, so I don't know how you tell Entity Framework to create indexes in the Code First scenario, sorry. But you still need to optimize all of your queries.
Upvotes: 0
Reputation: 37672
I hope this info will be useful.
Try to add indexes to fields of your table you are including to WHERE in LINQ.
You can always can create extra Views and add it into EF model and do LINQ to them. It will reduce time as well.
If you expect 1 record always try to use SingleOrDefault
Upvotes: 1
Reputation: 10548
Try:
objAdWord.Campaigns.FirstOrDefault(c => c.CampaignID == iElementCampaignID && c.Day == sElementDate)
.Where
is an O(n) operation, I'm not sure if the Where
then FirstOrDefault
clause would be optimized but if it's not you're wasting a lot of time using Where
. To improve performance further, ensure that CampaignID
is indexed
Upvotes: 0