1

为什么我的模型再次输出到数据库中以获取已在单独的 LINQ 连接语句中加载的相关属性?

背景资料:

我最近在我的 ASP.NET MVC3 Linq 应用程序上运行了一些性能分析,我得到了一些我希望解决的令人费解的结果。

这是 db 结构的简化版本。外键关系建立。

表客户端:

ID|Client Name|Vertical ID|
___________________________
1 |Client1    |2          |
2 |Client2    |5          |
3 |Client3    |           |

表垂直

ID|Vertical Name|
_________________
2 |Life         |
5 |Guilt        |

当我显示客户列表时,我向他们显示客户名称和垂直。我的控制器很简单:

public ActionResult Index()
    {
        ...
    var model = repository.GetAllClients();
        return View(model);
    }

获取所有客户端在垂直表(以及其他一些)上运行连接。

 public IEnumerable<client> GetAllClients()
    {
        OperationsMetricsDataContext db = new OperationsMetricsDataContext();
        var clients = from c in db.clients
                      join v in db.verticals on c.vertical equals v into tmp1
                      from v in tmp1.DefaultIfEmpty()
                      join sm in db.cel_sm_staffs on c.sm_id equals sm.cel_sm_id into tmp2
                      from sm in tmp2.DefaultIfEmpty()
                      join cel in db.cel_sm_staffs on c.cel_id equals cel.cel_sm_id into tmp3
                      from cel in tmp3.DefaultIfEmpty()
                      select c;
        return clients;
    }

然后,在我的视图中,我尝试在部分客户端类中显示我使用此方法绑定的垂直名称

public string getVerticalName()
    {
        return this.vertical == null ? "N/A" : this.vertical.vertical_name;
    }

问题:

@foreach (var item in Model) {
<tr>
    <td>
        @Html.Raw(item.client_name)
    </td>
    <td>
        @Html.Raw(item.getVerticalName())
    </td>

我发现的问题是,即使我在原始模型中指定了连接(并且我已经能够验证在模型传递给视图之前垂直属性是否加载了一个值),但每次我调用getVerticalName 方法,Linq 会自动再次到 db 中加载垂直,以便我可以访问垂直名称。这是非常低效的,因为我最终为每个客户单独调用了一个数据库,只是为了获取他们的垂直信息。

我在这里想念什么?LINQ 不应该知道该属性已经绑定并且不去数据库检索它,还是我需要指定一些东西来告诉 LINQ 我的信息已经存在于模型中?

4

2 回答 2

2

不确定它在 MVC 中的行为方式,但也许您的问题是延迟加载相关实体。您可以使用 LoadOptions 强制 Linq-2-sql 急切加载。

尝试

OperationsMetricsDataContext db = new OperationsMetricsDataContext();

DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<Client>(c => c.Vertical);
db.LoadOptions = dlo;
于 2012-11-06T22:53:12.027 回答
0

我的第一印象是让查询只执行一次,你应该改变return clients;return clients.ToList();

正如您的代码一样,我相信它会返回一个IQueryable简单的转换 as IEnumerable,并且根据设计 IQueryable 将在其枚举的任何时候转到服务器。

于 2012-11-06T22:38:37.857 回答