1

最近一个项目的性能测试使我重新设计了我的模型,并摆脱了嵌套模型。我将尝试详细说明我所看到的内容,希望有人能纠正我的理解。

我从具有嵌套地址的位置模型开始。

public class Location
{
    [Key]
    public int LocationId { get; set; }
    public string Name { get; set; }
    public int? AddressId {get;set;}
    public virtual Address Address{get;set;}
}
public class Address
{
    [Key]
    public int AddressId {get;set;}
    public string Street1 { get; set; }
    public string Street2 { get; set; }
    public string Street3 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
}

该模型在控制器中填充了 LINQ(cms 是我的 DbContext 并包含用于位置和地址的 DbSet):

public ActionResult ListLocations()
{    
    return View((from l in cms.Locations select l).ToList());
}

该视图是一个简单的循环,用于在表格中显示位置。

<table id="myTable" class="tablesorter">
    <thead>
        <tr>
            <th>Name</th>
            <th>City</th>
            <th>State</th>
            <th>Zip</th>
        </tr>
    </thead>
    <tbody>
        @if (Model != null)
        {
            foreach (var item in Model)
            {
            <tr>
                <td>@item.Name</td>
                <td>@item.Address.City</td>
                <td>@item.Address.State</td>
                <td>@item.Address.Zip</td>
            </tr>
            }
        }
    </tbody>
</table>

此方法按预期工作,但平均需要大约 2000 毫秒才能完成。我添加的每个额外位置都会使响应慢约 120 毫秒。

使用 Stack Exchange 的 MiniProfiler,我能够将每 120 毫秒的延迟精确到第一次“检索”地址以进行显示。如果后续位置具有相同的地址,则重复显示的性能成本是微不足道的。在所有情况下,“名称”属性检索都是微不足道的。

似乎嵌套模型没有与父模型同时检索。

当我通过将 Address 的属性直接组合到 Location 中来展平模型时。我能够以平均 300 毫秒的速度执行一个完整的请求,在添加更多位置时对此响应进行微不足道的更改。

我的问题- 实体框架是否提供了一种一次性缓存或检索嵌套模型的方法,或者这种嵌套模型的惰性实例化是否符合惯例?有没有一种方法可以在嵌套模型方法与平面模型中实现相似的响应时间?

与往常一样,选项 c) 的可能性我是否遗漏了一些明显的东西?

4

1 回答 1

2

尝试使用该Include方法在查询中包含地址。就像:

return View((from l in cms.Locations.Include("Address") select l).ToList());

http://msdn.microsoft.com/en-us/library/bb738708.aspx

您的代码现在正在执行查询以获取列表中每个位置的地址。如果您没有指定要在查询中获取哪些项目,EF 会进行延迟加载,并且它需要的每个对象都会生成一个新查询。

于 2012-12-05T23:39:26.780 回答