【问题标题】:create new property in new object from linq从 linq 在新对象中创建新属性
【发布时间】:2013-03-20 23:25:42
【问题描述】:

所以我正在执行 linq-to-sql 查询,结果以 IEnumerable 的形式出现。从这个列表中,我为每个返回的结果创建一个新对象。我已经使用的存储过程正在按我想要的顺序返回对象。我们有一个排行榜,查询后结果按降序排列。我遇到问题的部分是我想将排名添加到新对象的新属性中。

说我有这个代码

 var usersSummary = Context.[myStoredProcedure]
            return usersSummary.Select(x => new [myObject]
            {
                UserId = x.UserID,
                FirstName = x.FirstName,
                LastName = x.LastName,
                TotalPoints = x.TotalPoints,
                LeaderBoardRank = //this part here
                Email = x.Email,
                CreatedDate = x.CreatedDate
            }).OrderByDescending(x => x.TotalPoints).ToList();

我希望LeaderBoardRank 成为他们的排名。它们已经按排名顺序排序,因此第一个对象将是 1 ,接下来是 2 ,依此类推。由于这不是一个普通的 c# 循环,我不太清楚如何用排名填充这个属性。

【问题讨论】:

    标签: c# .net linq


    【解决方案1】:

    Select 作为重载,带有可以使用的索引。

        var usersSummary = Context.[myStoredProcedure]
            return usersSummary.Select((x, i) => new [myObject]
            {
                UserId = x.UserID,
                FirstName = x.FirstName,
                LastName = x.LastName,
                TotalPoints = x.TotalPoints,
                LeaderBoardRank = i
                Email = x.Email,
                CreatedDate = x.CreatedDate
            }).OrderByDescending(x => x.TotalPoints).ToList();
    

    您正在创建的对象是否已经是您列表中的对象?在这种情况下,您不必创建新对象,只需将值分配给现有对象即可:

        var usersSummary = Context.[myStoredProcedure]
            return usersSummary.Select((x, i) => 
                {
                    x.LeaderBoardRank = i;
                    return x;
                }).OrderByDescending(x => x.TotalPoints).ToList();
    

    此外,如果您的清单已经订购,则无需再次订购。您的 select 语句不会更改顺序。

    【讨论】:

    • 我现在要试试这个 - 它是一个真正的新对象,并且排序是在创建对象之后,在分配排名之后,然后我想按总分排序 - 哪个其实排名不一样
    • 这种重载是否适用于给定的查询提供程序。我知道至少其中一些无法使用索引器实现选择。
    • @Servy 不幸的是,这种重载不适用于 Linq-to-sql 或 Linq-to-entities。它很有用,可以在 Sql 中实现,但尚不支持。对于 Linq-to-entities,您可以在 Codeplex 网站上添加请求,甚至可以自己实现(EF6 Alpha 是开源的)。
    • @JustAnotherUserYouMayKnow 那么这个答案将不起作用。您需要在不使用数据库索引器的情况下执行查询,进行排序,然后添加 AsEnumerable 并使用带有索引器的 Select 来添加该属性。
    • @Servy 对我来说,您可以将 Sql 包装在存储过程的执行周围,因此您不会从代码中调用的存储过程中获得 IQueryable 并且 select 语句不会更改查询。但是我必须管理我不熟悉 Linq-to-sql,但是使用 EF 会是这种情况,我的解决方案会起作用。
    【解决方案2】:

    如果“新属性”是指LeaderBoardRank 不是myObject 的属性,那么不,你不能这样做。您要么需要定义另一个类(可能扩展 MyObject),要么使用匿名类型,或者使用该附加属性或使用两个属性 - 等级和对象。

    如果LeaderBoardRank 已经是一个属性并且你想添加排序结果的排名,你可以这样做:

    var usersSummary = Context.[myStoredProcedure];
    
    return usersSummary.OrderByDescending(x => x.TotalPoints)
                       .Select((x, i) => new [myObject]
    {
        UserId = x.UserID,
        FirstName = x.FirstName,
        LastName = x.LastName,
        TotalPoints = x.TotalPoints,
        LeaderBoardRank = i
        Email = x.Email,
        CreatedDate = x.CreatedDate
    }).ToList();
    

    请注意,这不考虑平局 - 这意味着如果两个用户的总分相同,他们将不会获得相同的排名。

    【讨论】:

    • 昨天没机会测试,不过很好用,谢谢
    猜你喜欢
    • 2019-02-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-29
    • 1970-01-01
    • 1970-01-01
    • 2011-01-23
    • 2018-07-16
    • 1970-01-01
    相关资源
    最近更新 更多