【问题标题】:MVC4, public virtual ICollection, how to set sort orderMVC4,公共虚拟ICollection,如何设置排序顺序
【发布时间】:2014-03-11 17:00:41
【问题描述】:

我有一个使用 Code First EF 5 的 MVC4 项目。

我有使用公共虚拟 ICollection 的模型,我想设置这些集合中项目的显示顺序。

例如:

假设我有一个订单模型:

public class Order
{
 public virtual ICollection<OrderItem> Items { get; set; }
}

和一个 OrderItems 模型:

public Class OrderItem
{
 public int ID;
 public string name;
 public decimal price;
}

我想为每个订单设置 OrderItem 集合的 Order 以降序显示。我该怎么做呢?或者,事实上,有可能吗?

我已尝试添加:

 this.Items.OrderByDescending(OrderItem,"price");

到订单模型构造器(胖模型,瘦控制器?)

我也尝试将它添加到控制器动作和视图中,但都没有奏效。

我猜在 DbContext 中可能有一些方法可以做到这一点,但我不得不承认我有点迷路了。

更新:到目前为止,我已根据建议尝试了以下解决方案,但无济于事。

    private ICollection<OrderItem> _Items;
    public virtual ICollection<OrderItem> Items
    {
        get { return _Items.OrderByDescending(item => item.Price).ToList(); }
        set { _Items = value; }
    }

这产生了这个错误:值不能为空。参数名称:来源

我需要在构造函数中添加一些东西吗?

我还尝试在模型中添加一个构造函数以及以下内容:

public OrderItem()
{
this.Items = this.Items.OrderByDescending(i => i.Price).ToList();
}

这没有任何效果。

我也试过了:

this.Items = this.Items.OrderByDescending(OrderItem, "price").ToList();

这会产生错误“OrderItem 是一种类型,但用作变量”。

大家有什么想法吗?

好的。我刚刚将此添加到我的控制器中的详细信息方法中:

public ActionResult Details(int id = 0)
{
  order.Items = order.Items.OrderByDescending(item => item.price).ToList();         
}

哪个有效。如果可能的话,我仍然想知道为什么会得到;放;解决方案并不仅仅供将来参考。延迟加载、急切加载和显式加载之间的区别在这里也有任何相关性吗?

非常感谢。

好的,所以我尝试了 Ken4z 的建议并补充说:

public Order()
{
_Items = new List<OrderItem>();
}

这可以防止任何错误,但在控制器中调用该操作时实际上不会加载任何项目。可能是一个愚蠢的问题,但无论如何我都会问:

set { _Items = value; }  

不是构造函数现在将 value 作为 A List Of OrderItem 传递,其中没有任何内容吗?试图完全掌握这一点。再次感谢您的帮助。

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-4 ef-code-first


    【解决方案1】:
    var orderedItems = Items.OrderByDescending(item => item.price);
    

    编辑 1:

    根据 David 的评论,我将“Set”解释为,您希望 Items 集合的访问器默认按价格降序返回。在这种情况下,您将需要实现 getter。

    public class Order
    {
        private ICollection<OrderItems> _items;
        public virtual ICollection<OrderItems> Items 
        {
            get{ return _items.OrderByDescending(item => item.price); }
            set{ _items = value; }
        }
    }
    

    编辑 2: 感谢 David 指出错误。

    public class Order
    {
        public Order()
        {
            _items = new List<OrderItems>();
        }
    
        private ICollection<OrderItems> _items;
        public virtual ICollection<OrderItems> Items 
        {
            get{ return _items.OrderByDescending(item => item.price).ToList(); }
            set{ _items = value; }
        }
    }
    

    【讨论】:

    • 这里不解释如何设置属性。
    • 我不明白你的批评,你答案的最后一行除了将它转换为 ToList();
    • 这会将结果分配给一个变量,但问题是如何将它分配给类中的 Items 属性。这样做,我会很乐意推翻我的投票。
    • 啊。好点子。应该在发帖前把它放在VS中。我确实认为将逻辑放在 getter(或 setter)中而不是仅仅设置 this.Items 更好,这样任何使用 Items 的类都会以所需的顺序获取它。或者,如果你想在类中使用有序的项目,你可以把它放在 setter 中。
    • 这是一个哲学问题,取决于您的架构、应用程序的大小和规模,以及与您合作的人的意见等。
    【解决方案2】:
    this.Items.OrderByDescending(OrderItem,"price");
    

    LINQ 方法返回一个新实例,因此您必须设置这个结果:

    this.Items = this.Items.OrderByDescending(OrderItem, "price").ToList();
    

    注意ToList(),因为结果是IEnumerable&lt;T&gt;ICollection&lt;T&gt; : IEnumerable&lt;T&gt;,但IEnumerable&lt;T&gt; 不是ICollection&lt;T&gt;List&lt;T&gt; : ICollection&lt;T&gt;.

    您还可以使用 LINQ 方法的“更清洁”、类型安全的版本:

    this.Items = this.Items.OrderByDescending(i => i.price).ToList();
    

    【讨论】:

      【解决方案3】:

      如果您最终经常需要排序的 ICollection 导航属性,您可以随时添加如下内容: [NotMapped] public IList<OrderItem> ItemsSorted {get {return Items?.OrderBy(p=>p.price).ToList(); }}

      对于您的域实体,这样当您在控制器或其他代码中使用它时,您不必经常明确地对内容进行排序。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-18
        • 2012-09-20
        • 1970-01-01
        • 2012-12-15
        相关资源
        最近更新 更多