Linq查询被多次触发,没有任何明显的原因

时间:2011-04-01 00:27:13

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

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

是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 =&gt; c.id == id)要求排名前2?像这样:

选择TOP(2) [Extent1]。[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”中设置了一个断点,在控制器的“返回视图(myModel)”中放了一个断点。

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

这让我发疯了!

2 个答案:

答案 0 :(得分:6)

  

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

     

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

如果没有一个匹配项,则

Single()会抛出异常 - 因此Linq to Entities提供程序将其转换为top 2查询,这是足以做出决策的数据 - 如果查询则抛出异常返回2个结果或者没有,否则返回唯一的结果。

答案 1 :(得分:1)

这没有意义。如果多次执行查询,则必须多次调用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我描述了适用于不同密钥类型和名称的完整示例。