【问题标题】:Linq query is triggered multiple times without any apparent reasonLinq 查询被多次触发,没有任何明显的原因
【发布时间】:2011-04-02 04:32:09
【问题描述】:

我正在尝试优化我的应用,但我注意到一个查询被多次触发而没有任何明显的原因。

是一个 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 都完全相同。
  • 事务ID不同,也 持续时间略有不同。
  • 其余的都差不多。

知道什么可以让这个查询多次运行吗?

另一个问题!

有人知道为什么 db.companies.Single(c => c.id == id) 要求前 2 名吗?像这样:

选择顶部 (2) [Extent1].[id] AS [id], ....

提前致谢!

埃德加。

更新!

第三次调用是我的错,我修复了它。 但是,我发现:

应用程序是多语言的,所以我写了一个实现Controller的类。

我将问题追溯到这个类。当我调用 Base 时,第二次在课程结束时触发查询:

base.Execute(requestContext);

当然,该动作会再次被调用。

任何想法如何防止这种情况?

另一个更新!

Linkgoron 询问我为什么调用 Base.Execute(),答案是因为本地化控制器的实现。

但他的问题让我思考,代码中还有另一部分:

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)” 中设置了一个断点。

当我调用视图 companyDetail 时,第一站在 base.Execute 中,第二站在返回视图中,但由于某种原因,在 Base.Execute 中有第三站,在 Return View 中有第四站,最后是视图正在渲染。

这让我发疯了!

【问题讨论】:

  • 您是否尝试过在调试器中逐步运行并查看查询的执行位置?
  • 检查您的操作方法在浏览器获取周期中仅被调用一次。错误的 HTML 可能会导致操作方法的重复执行。我以前见过导致此类问题的格式错误的图像标签。
  • 为什么要调用base execute?

标签: linq entity-framework asp.net-mvc-3


【解决方案1】:

任何人都知道为什么 db.companies.Single(c => c.id == id) 要求前 2 名?像这样:

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

Single() 如果不完全匹配,则抛出异常 - 因此 Linq to Entities 提供程序将其转换为 top 2 查询,该查询足以做出决定 - 如果查询返回 2 个结果或无,否则返回唯一的结果。

【讨论】:

  • 谢谢!我不知道我是怎么想念的!
【解决方案2】:

这没有意义。如果查询多次执行,您必须多次调用GetCompany 方法。一旦您调用Single,查询就会被执行并且Company 实例会被物化,因此在视图中多次使用它不会导致新的执行。那些另一个调用必须是由您的代码的不同部分引起的。

顺便说一句。您可以使用 Find(在 EF 4.1 中)或 GetObjectByKey(在 EFv1 和 EFv4 中)而不是 Single 来避免它们。 Single 总是在数据库中执行查询,而 Find 首先检查是否已经加载了具有相同实体键的实体并返回实例而不执行数据库查询:

这是 DbContext API (EF 4.1) 的代码:

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

ObjectContext API 的代码有点复杂,因为您首先必须构建需要实体集名称的EntityKeyHere 我描述了使用不同键类型和名称的完整示例。

【讨论】:

    猜你喜欢
    • 2021-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多