Linq-запрос запускается несколько раз без видимой причины. - PullRequest
2 голосов
/ 01 апреля 2011

Я пытаюсь оптимизировать свое приложение и замечаю, что один запрос запускается несколько раз без видимой причины.

Является ли приложение MVC 3 бритвой, и я использую Linq и EF.

У меня есть класс ViewModel с несколькими свойствами.Одним из этих свойств является модель для просмотра.

Это мой контроллер (я пропускаю все остальные свойства инициализации):

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

Этомой метод getCompany:

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

    }

Представление слишком длинное для вставки, но это простое представление.Это часть, например:

<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>

Я использую AnjLab SQL Profiler для просмотра транзакций ..

  • Когда я вызываю представление, запрос этозвонил 3 раза.
  • Сгенерированный SQL одинаков для всех 3.
  • Идентификатор транзакции отличается, а также продолжительность немного меняется.
  • Остальные в значительной степени одинаковы.

Есть идеи, что может заставить этот запрос выполняться несколько раз?

Другой вопрос!

Кто-нибудь знает, почему db.companies.Single (c => c.id == id) запрашивает топ-2?Например:

ВЫБРАТЬ ТОП (2) [Экстент1]. [Id] AS [id],….

Заранее спасибо!

Эдгар.

Обновление!

Третий звонок был моей ошибкой, и я исправляю ее. Однако , я нахожу это:

Приложение многоязычное, поэтому я пишу класс, который реализует Controller.

Я прослеживаю проблему для этого класса.Запрос запускается второй раз в конце класса, когда я вызываю Base:

base.Execute(requestContext);

и, конечно, действие вызывается снова.

Любая идея, как это предотвратить?

Еще одно обновление!

Linkgoron спрашивает, почему я вызываю Base.Execute (), ответ из-за реализации localizedController.

Но его вопрос заставляет меня задуматься, и есть другая часть кода:

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);
}
}

Мой контроллер определен так:

public class companiesController : LocalizedControllerBase

Я поставилточка останова в «Base.Execute» и другая в «return View (myModel)» в контроллере.

Когда я вызываю view companyDetail, первыйstop находится в base.Execute, второй находится в обратном представлении, но по какой-то причине в Base.Execute есть третий и четвертый в возвращаемом представлении, и, наконец, представление отображается.

Это делаетя сумасшедший!

Ответы [ 2 ]

6 голосов
/ 01 апреля 2011

Кто-нибудь знает, почему db.companies.Single (c => c.id == id) спросить топ 2? Как это:

SELECT TOP (2) [Экстент1]. [Id] AS [id], ....

Single() выдает исключение, если не существует только одного совпадения - поэтому провайдер Linq to Entities преобразует его как запрос top 2, который является достаточным для принятия решения. Выдает исключение, если запрос возвращает 2 результата или в противном случае верните единственный результат.

1 голос
/ 01 апреля 2011

Это не имеет смысла. Если запрос выполняется несколько раз, вы должны вызывать метод GetCompany несколько раз. Как только вы вызываете Single, запрос выполняется, и экземпляр Company материализуется, поэтому использование его несколько раз в поле зрения не вызовет новых исполнений. Эти другие вызовы должны быть вызваны другой частью вашего кода.

Btw. вы можете избежать их, используя Find (в EF 4.1) или GetObjectByKey (в EFv1 и EFv4) вместо Single. Single всегда выполняет запрос в базе данных, тогда как Find сначала проверяет, был ли объект с тем же ключом сущности уже загружен, и возвращает экземпляр без выполнения запроса db:

Это код для DbContext API (EF 4.1):

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

Код для ObjectContext API немного сложен, потому что сначала нужно построить EntityKey, для которого требуется имя набора сущностей. Здесь Я описал полный пример, который работает с различными типами ключей и именами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...