元素未添加到列表中

时间:2013-07-19 12:20:03

标签: c# linq nhibernate

我有一个名为Estimate的类,它有以下字段和属性:

private IList<RouteInformation> _routeMatrix;
public virtual IList<RouteInformation> RouteMatrix
{
    get
    {
        if (_routeMatrix != null && _routeMatrix.Count > 0)
        {
            var routeMatrix = _routeMatrix.ToList();
            routeMatrix =
                    routeMatrix.OrderBy(tm => tm.Level.LevelType).ThenBy(tm => tm.Level.LevelValue).ToList();
            return routeMatrix;
        }
        else return _routeMatrix;
    }
    set { _routeMatrix = value; }
}

因此,在getter方法中,我只是按级别类型排序_routeMatrix,然后按级别值排序并返回排序列表。

在我的一个程序中,我有以下代码:

public void SaveApprovers(string[] approvers)
{
    int i = 1;
    foreach (var approver in approvers)
    {
        var role = Repository.Get<Role>(long.Parse(approver));
        var level = new Models.Level
        {
            LevelType = LevelType.Approver,
            LevelValue = (LevelValue)i,
            Role = role
        };
        Repository.Save(level);
        var routeInformation = new Models.RouteInformation
        {
            Level = level,
            RouteObjectType = RouteObjectType.Estimate,
            RouteObjectId = _estimate.Id
        };
        Repository.Save(routeInformation);
        _estimate.RouteMatrix.Add(routeInformation); // <--- The problem is here
        Repository.Save(_estimate);
        i++;
    }
}

问题在于,如果有多个批准者(即:approvers数组的长度大于1,则只会在routeInformation中添加第一个RouteMatrix。不知道其他人发生了什么,但Add方法没有给出任何错误。

早些时候,RouteMatrix是一个公共领域。在我将其设为私有并将其封装在公共属性中之后,这个问题就开始出现了。

3 个答案:

答案 0 :(得分:2)

当您应用ToList()时,会创建一个全新的列表,该列表与原始_routeMatrix列表无关。好吧,它们共享相同的元素,但是当你从一个列表中添加或删除元素时,它不会影响第二个列表。

来自MSDN

  

您可以将此方法附加到查询中以获取缓存   查询结果的副本。

因此,您已缓存了您正在成功修改的_routeMatrix复制


要解决此问题,您可以返回 IEnumerable 而不是 IList (禁用估算类之外的集合修改),并为估算类创建AddRouteInformation方法这会将路线信息添加到_routeMatrix。使用该方法添加新项目:

_estimate.AddRouteInformation(routeInformation);
Repository.Save(_estimate);

答案 1 :(得分:2)

您的get成员返回不同的列表,您将添加到该临时列表中。

 get
 {
    if (_routeMatrix != null && _routeMatrix.Count > 0)
    {
        var routeMatrix = _routeMatrix.ToList(); // ToList creates a _copy_ of the list
        ...
        return routeMatrix;
    }
    else return _routeMatrix;
 }

 .....

 _estimate.RouteMatrix.Add(routeInformation);   // add to the result of ToList()

我认为这里的道德观点并不是让吸气剂过于复杂。当您只想添加()时,排序是浪费精力。

此外,_routeMatrix == null时会发生不好的事情。这可能不会发生,但if (_routeMatrix != null && ...)部分会产生误导性噪音。

答案 2 :(得分:1)

问题是你实际上并没有修改_routeMatrix,而是修改了它的副本。不要在ToList上发出_routeMatrix,只需对其进行排序即可。将get更改为此:

get
{
    if (_routeMatrix != null && _routeMatrix.Count > 0)
    {
        _routeMatrix =
                _routeMatrix.OrderBy(tm => tm.Level.LevelType).ThenBy(tm => tm.Level.LevelValue).ToList();
        return _routeMatrix;
    }
    else return _routeMatrix;
}