2

I’m trying to optimize my app, and I notice that one query is triggered multiple times without any apparent reason.

Is a MVC 3 App, razor and I’m using Linq and EF.

I have ViewModel class with a couple of properties. One of these properties is the model for to view.

This is my controller (I omit all the others properties initialization):

public ActionResult companyDetail(Guid id)
    {
        companyDetailsViewModel myModel = new companyDetailsViewModel();
        myModel.companyDetail = companiesRepository.getCompany(id);
        return View(myModel);
    }

This is my getCompany method:

public company getCompany(Guid id)
    {
        return db.companies.Single(c => c.id == id); 

    }

The view is too long to paste here, but is a simple view. This is a part for example:

<div id="companyName">
<h2>
     @Model.companyDetail.companyName
</h2>
</div>
<div id="companyInfoWapper">
     <div class="companyInfo">
    <h5>
    industry: @Model.companyDetail.industry<br />
    revenue:  @String.Format("{0:C}", Model.companyDetail.revenue)
        </h5>        
     </div>
</div>

I’m using AnjLab SQL Profiler to view the transactions..

  • When I call the view, the query it’s called 3 times.
  • The Generated SQL is the exact same on all 3.
  • The transaction ID is different, and also the duration varies a little bit.
  • The rest are pretty much the same.

Any Idea what can be making this query to run multiple times?

Another Question!

Anyone know why db.companies.Single(c => c.id == id) ask for top 2? Like this:

SELECT TOP (2) [Extent1].[id] AS [id], ….

Thanks in Advance!

Edgar.

Update!

The third call was my fault, and I fix it. However, I find this:

The application is Multi-language, so I write a class that implements Controller.

I trace the problem to this class. The query is triggered the second time at the end of the class when I call the Base:

base.Execute(requestContext);

and of course, the action is called again.

Any Idea how to prevent this?

Another Update!

Linkgoron ask why I call Base.Execute(), the answer is because of the localizedController implementation.

But his question make me think, and there is another part of the code:

public abstract class LocalizedControllerBase : Controller
{    

public String LanguageCode { get; private set; }

private String defaultLanguage = "es";
private String supportedLanguages = "en|es|pt";

protected override void Execute(RequestContext requestContext)
{
    if (requestContext.RouteData.Values["languageCode"] != null)
    {
        LanguageCode = requestContext.RouteData.Values["languageCode"].ToString().ToLower();

        if (!supportedLanguages.ToLower().Contains(LanguageCode))
        {
            LanguageCode = defaultLanguage;
        }


    }
    else {
        LanguageCode = defaultLanguage;
    }

    System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CreateSpecificCulture(LanguageCode);

    Thread.CurrentThread.CurrentCulture = culture;
    Thread.CurrentThread.CurrentUICulture = culture;

    base.Execute(requestContext);
}
}

My controller are defined like this:

public class companiesController : LocalizedControllerBase

I put a break point in “Base.Execute” and another in the “return View(myModel)” in the controller.

When I call the view companyDetail, the first stop is in base.Execute, the second is in return view, but for some reason there is a third stop in Base.Execute and a fourth in Return View, and finally the view is render.

This is making me crazy!

epaulk
  • 309
  • 1
  • 4
  • 15
  • Have you tried running in debugger step-by-step and looking where the queries are executed? – Linkgoron Apr 01 '11 at 01:09
  • Check that your action method is only being called once during the browser fetch cycle. Faulty HTML could be causing the repeated execution of the action method. I've seen malformed image tags causing issues like this before. – Ian Mercer Apr 01 '11 at 06:06
  • why are you calling base execute? – Linkgoron Apr 01 '11 at 17:27

2 Answers2

6

Anyone know why db.companies.Single(c => c.id == id) ask for top 2? Like this:

SELECT TOP (2) [Extent1].[id] AS [id], ….

Single() throws an exception if there is not exactly one match - so the Linq to Entities provider translates that as a top 2 query which is enough data to make a decision - throw an exception if the query returns 2 results or none, return the only result otherwise.

BrokenGlass
  • 158,293
  • 28
  • 286
  • 335
1

This doesn't make sense. If the query is executed multiple times you must call GetCompany method multiple times. Once you call Single the query is executed and Company instance is materialized so using it multiple times in view will not cause new executions. Those another calls must be caused by different part of your code.

Btw. you can avoid them by using Find (in EF 4.1) or GetObjectByKey (in EFv1 and EFv4) instead of Single. Single always executes query in database whereas Find first checks if the entity with the same entity key was already loaded and returns the instance without executing db query:

This is code for DbContext API (EF 4.1):

public company getCompany(Guid id)
{
    // Id must be primary key
    return db.companies.Find(id); 
}

Code for ObjectContext API is little bit complicated because you first have to build EntityKey which requires entity set name. Here I described full example which works with different key types and names.

Community
  • 1
  • 1
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670