相关模型的LINQ冗余DB访问



为什么我的模型再次出现到已经加载在单独的linq join语句中的相关属性的DB上?

背景信息:

我最近在我的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以加载垂直方向,以便我可以访问垂直名称。这是非常低效的,因为我最终会为每个客户提供一个单独的DB呼叫,只是为了获取垂直信息。

我在这里想念什么?Linq不应该知道该属性已经被绑定并且不出去DB检索它,或者我需要指定一些内容来告诉Linq我的信息已经存在于模型中了吗?

不确定其在MVC中的表现,但也许您的问题是懒惰加载相关实体。您可以使用Loadoptions强迫Linq-2-SQL急切地加载。

尝试

OperationsMetricsDataContext db = new OperationsMetricsDataContext();
DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<Client>(c => c.Vertical);
db.LoadOptions = dlo;

我的第一个印象是,一旦您要更改,才能使查询仅执行: return clients; to return clients.ToList();

作为您的代码,我相信它正在返回IQueryable,仅以IEnumerable施放,并且通过设计可让您随时列举服务器。

最新更新