如何将行号投影到 Linq 查询结果中
Posted
技术标签:
【中文标题】如何将行号投影到 Linq 查询结果中【英文标题】:How To Project a Line Number Into Linq Query Results 【发布时间】:2010-09-26 18:39:06 【问题描述】:如何将行号投影到 linq 查询结果集。
而不是说:
字段1,字段2,字段3
字段1,字段2,字段3
我想要:
1,字段1,字段2,字段3
2,字段1,字段2,字段3
这是我的尝试:
public List<ScoreWithRank> GetHighScoresWithRank(string gameId, int count)
Guid guid = new Guid(gameId);
using (PPGEntities entities = new PPGEntities())
int i = 1;
var query = from s in entities.Scores
where s.Game.Id == guid
orderby s.PlayerScore descending
select new ScoreWithRank()
Rank=i++,
PlayerName = s.PlayerName,
PlayerScore = s.PlayerScore
;
return query.ToList<ScoreWithRank>();
很遗憾,“Rank=i++”行会引发以下编译时异常:
“表达式树不能包含赋值运算符”
【问题讨论】:
How do you add an index field to Linq results的可能重复 【参考方案1】:嗯,最简单的方法是在客户端而不是数据库端执行此操作,并使用 Select 的重载,它也提供索引:
public List<ScoreWithRank> GetHighScoresWithRank(string gameId, int count)
Guid guid = new Guid(gameId);
using (PPGEntities entities = new PPGEntities())
var query = from s in entities.Scores
where s.Game.Id == guid
orderby s.PlayerScore descending
select new
PlayerName = s.PlayerName,
PlayerScore = s.PlayerScore
;
return query.AsEnumerable() // Client-side from here on
.Select((player, index) => new ScoreWithRank()
PlayerName = player.PlayerName,
PlayerScore = player.PlayerScore,
Rank = index + 1;
)
.ToList();
【讨论】:
从数据库中获取所有内容并不是真正的“解决方案” @DotNetWise:它没有从数据库中获取 everything - 只有与查询匹配的位。它只是从数据库中获取与最初尝试相同数量的数据 - 只是做了一点后处理。 怎么样? query.AsEnumerable() 将为给定的 gameId 提供所有匹配的记录。尽量只占据排名在第 20 位之后的位置。您将从数据库中获取所有内容以获得排名,然后删除您需要的内容。不是真正想要的解决方案!除此之外 - count 参数在哪里使用? @DotNetWise:我同意count
参数尚未被使用,但只要在AsEnumerable()
调用之前 使用它就可以了。特别是,where
子句和orderby
子句在AsEnumerable
之前使用,因此所有过滤都将在数据库中进行。正如我在之前的评论中所说,它只获取与查询匹配的记录......换句话说,无论如何都需要数据。如果您想获得排在第 20 位之后的位置,您可以向query
添加Skip
调用,或使用query.Skip(20).AsEnumerable()
。 (然后您需要调整 Rank
计算。)
@MikeKulls:所以仅仅因为你不能用 LINQ 做所有数据库的东西,你就没有做吗?对我来说,这听起来像是把婴儿和洗澡水一起扔出去。【参考方案2】:
好的,成功了。谢谢。
这是我的最终代码...
服务器:
public List<Score> GetHighScores(string gameId, int count)
Guid guid = new Guid(gameId);
using (PPGEntities entities = new PPGEntities())
var query = from s in entities.Scores
where s.Game.Id == guid
orderby s.PlayerScore descending
select s;
return query.ToList<Score>();
客户:
void hsc_LoadHighScoreCompleted(object sender, GetHighScoreCompletedEventArgs e)
ObservableCollection<Score> list = e.Result;
_listBox.ItemsSource = list.Select((player, index) => new ScoreWithRank()
PlayerName = player.PlayerName,
PlayerScore = player.PlayerScore,
Rank = index+=1
).ToList();
【讨论】:
你真的需要 GetHighScores() 来返回 ListRank = index += 1
会不会比Rank = index+1
更好?【参考方案3】:
您也可以对原始代码稍作调整以使其正常工作。请注意,如果您再次数据绑定或访问该对象,Rank 将每次递增。在这些情况下,最佳答案更好。
let Rank = i++
和
Rank.ToString()
完整代码:
public List<ScoreWithRank> GetHighScoresWithRank(string gameId, int count)
Guid guid = new Guid(gameId);
using (PPGEntities entities = new PPGEntities())
int i = 1;
var query = from s in entities.Scores
let Rank = i++
where s.Game.Id == guid
orderby s.PlayerScore descending
select new ScoreWithRank()
Rank.ToString(),
PlayerName = s.PlayerName,
PlayerScore = s.PlayerScore
;
return query.ToList<ScoreWithRank>();
【讨论】:
这段代码甚至无法编译。它会生成错误 CS0832:表达式树可能不包含赋值运算符【参考方案4】:这个解决方案对我有用。 http://www.dotnetfunda.com/articles/article1995-rownumber-simulation-in-linq.aspx
.Select((x, index) => new
SequentialNumber = index + 1
,FieldFoo = x.FieldFoo
).ToList();
【讨论】:
实体框架不支持采用 Int32 参数的重载。请注意,dotNetFunda 上的文章使用 linq to objects。【参考方案5】:List<Emp> Lstemp = GetEmpList();
int Srno = 0;
var columns = from t in Lstemp
orderby t.Name
select new
Row_number=++Srno,
EmpID = t.ID,
Name = t.Name,
City = t.City
;
【讨论】:
以上是关于如何将行号投影到 Linq 查询结果中的主要内容,如果未能解决你的问题,请参考以下文章