Linq 查询在没有任何明显原因的情况下被多次触发
我正在尝试优化我的应用程序,我注意到一个查询在没有任何明显原因的情况下被多次触发。
是一个 MVC 3 应用程序、razor,我正在使用 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) [范围 1].[id] AS [id],...。
提前致谢!
埃德加.
更新!
第三次调用是我的错,我已修复它。 但是,我发现:
该应用程序是多语言的,所以我编写了一个实现控制器的类。
我将问题追溯到这个类。当我调用 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”中放置了另一个断点在控制器中查看(myModel)”。
当我调用视图companyDetail时,第一站是在base.Execute中,第二站是在return视图中,但由于某种原因,第三站是在Base.Execute中,第四站是在Return View中,最后视图被渲染。
这让我抓狂!
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!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果没有完全匹配,
Single()
会引发异常 - 因此 Linq to Entities 提供程序会将其转换为top 2
查询,该查询有足够的数据来做出决定 -如果查询返回 2 个结果或没有结果,则抛出异常,否则返回唯一的结果。Single()
throws an exception if there is not exactly one match - so the Linq to Entities provider translates that as atop 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.这没有道理。如果多次执行查询,则必须多次调用
GetCompany
方法。一旦您调用Single
,就会执行查询,并且Company
实例会被具体化,因此在视图中多次使用它不会导致新的执行。这些其他调用必须是由代码的不同部分引起的。顺便提一句。您可以通过使用
Find
(在 EF 4.1 中)或GetObjectByKey
(在 EFv1 和 EFv4 中)而不是Single
来避免它们。Single
始终在数据库中执行查询,而Find
首先检查具有相同实体键的实体是否已加载并返回实例而不执行数据库查询:这是 DbContext API 的代码(EF 4.1):
ObjectContext API 的代码有点复杂,因为您首先必须构建需要实体集名称的
EntityKey
。 这里我描述了适用于不同的密钥类型和名称。This doesn't make sense. If the query is executed multiple times you must call
GetCompany
method multiple times. Once you callSingle
the query is executed andCompany
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) orGetObjectByKey
(in EFv1 and EFv4) instead ofSingle
.Single
always executes query in database whereasFind
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):
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.