【问题标题】:Lazy loading navigation properties延迟加载导航属性
【发布时间】:2012-04-12 15:48:08
【问题描述】:

似乎我无法在我的域服务中的 include 上放置 where 子句 - 所以我们正在执行一些循环来获取某些 lookupGroups 所需的数据。

   var _lookupGroups = _lookupGroupRepository.All();
        var _lookupValues = _institutionLookupValueRepository.All().Where(x => x.InstitutionID == _userProfile.InstitutionID);

        int i = 0;

        foreach (var _group in _lookupGroups)
        {
            var _values = _lookupValues.Where(x => x.LookupGroupID == _group.LookupGroupID);

            foreach (var _value in _values)
            {
                _group.InstitutionLookupValues.Add(_value);

                i++;
            }

            Console.WriteLine(_group.GroupName + " " + i.ToString());
        }

        return _lookupGroups;

我输入的计数器是为了验证我所看到的 - 我们迭代的第一组是状态。我的计数器会说 50,但我的导航属性会说 100,显示我们拥有的每个机构的一组 50(我们有 2 组)。所以它正在获取所有查找值并将它们放入导航属性中,即使我的计数器显示为 50。我还删除了元数据文件中的所有包含。

澄清一下:我有附加到lookupGroups 的lookupvalues。查找值分配给机构。因此,如果我去获取 STATES 查找组的值,我将获得 50 个查找值。上面的代码。当我运行此行时 _group.InstitutionLookupValues.Add(_value);我的机构LookupValues = 100(无论机构如何,都采用所有lookupValues)。但我的计数器显示 50。在某处我得到了所有查找值,不确定与特定机构相关的值。

【问题讨论】:

  • 我不明白问题出在哪里。你的柜台是什么?数字不同有问题吗?
  • 谢谢 - 稍微更新了问题。

标签: c# entity-framework wcf-ria-services


【解决方案1】:

我认为这是由于您正在访问修改后的闭包这一事实造成的,即使不是,您也不应该这样做。线

var _values = _lookupValues.Where(x => x.LookupGroupID == _group.LookupGroupID);

可能没有做你认为它正在做的事情(除非它是 C#5)。 lambda 是一个委托,闭包将关闭变量,而不是值。这意味着您的代码 _group.LookupGroupID 将始终是枚举器最终迭代的最后一个值,因此您只会过滤一个 _group.LookupGroupID 上的查找值。

尝试将块更改为:

foreach (var _group in _lookupGroups)
{
  var currentGroup = _group;    
  var _values = _lookupValues.Where(x => x.LookupGroupID == currentGroup.LookupGroupID);

  foreach (var _value in _values)
  {
     currentGroup.InstitutionLookupValues.Add(_value);

     i++;
  }

  Console.WriteLine(currentGroup.GroupName + " " + i.ToString());
}

我不确定这是否是问题的原因,但无论如何你都会得到其他奇怪的效果。通过在循环中创建自己的变量,可以避免关闭生成的枚举变量。

查看 Eric Lippert 关于此的文章:Closing over the loop variable considered harmful。令人惊讶的是,很少有人知道这个问题。

另外,折叠查询可能是个好主意:

var _lookupValues = _institutionLookupValueRepository.All().Where(x => x.InstitutionID == _userProfile.InstitutionID);

使用ToList() 或类似名称。否则,您将针对 _lookupGroups 中的每个循环重新评估此查询,如果查询是针对数据库的,或者循环很大,这可能会对性能造成严重影响。

【讨论】:

  • 这是一个很好的分析 - 谢谢 - 我会试试这个并报告,谢谢。
  • 通过此代码更改仍然得到相同的结果 - 当它完成第一个 lookupGroup 时,我在该导航属性中看到 100 个状态。
  • 好吧,无论如何它都是有效的;)你是说每个_group(我假设它与一个EF表匹配,一开始在InstitutionLookupValues上有一个空集合吗?什么结果呢?如果你不运行 Add 方法,你会在循环之后得到 InstitutionLookupValues 吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多