【问题标题】:how to iterate with Linq to create list of objets?如何使用 Linq 迭代以创建对象列表?
【发布时间】:2019-05-19 08:50:03
【问题描述】:

我正在尝试使用 Linq 从列表中进行迭代,以创建并返回一个模型,其中包含项目列表和总项目数量。

必须返回的对象如下:

public class ListeArticlesModel
    {        
        public List<TuileArticleModel> Items { get; set; }

        public int Quantity { get; set; }

    }

我目前对此感到困惑:

result.Actualites = tousLesArticlesFromDb
                .ToList()
                .Where(
                    a => a.GetPropertyValue<IEnumerable<IPublishedContent>>("ficheArticle_typeDeContenu")
                             .FirstOrDefault()?.Name == @EnumResources.TypeDeContenu_Actualites)
                .OrderBy(a => a.CreateDate)
                .Take(criteriaModel.NbrItemsParPage)
                .Select(
                    a => new ListeArticlesModel
                    {
                        Items = new List<TuileArticleModel>
                        {
                            // returns a TuileArticleModel 
                            getItem(a)
                        },
                    })
                .FirstOrDefault();

这不是我想要的。如果我删除 .FirstOrDefault() 我会得到一个 IEnumerable

我知道我错过了一些东西。我正在为每个“a”项目构建一个新的 ListeArticleModel,然后我只使用第一个构建的项目,但我不知道如何离开这里......

(ps:我几周前毕业了。我是 C# 新手。我知道这可能是基础知识。我正在努力学习它们:D)

我试过这个:

var actus = tousLesArticlesFromDb
                    .ToList()
                    .Where(
                        a => a.GetPropertyValue<IEnumerable<IPublishedContent>>("ficheArticle_typeDeContenu")
                                 .FirstOrDefault()?.Name == @EnumResources.TypeDeContenu_Actualites)
                    .OrderBy(a => a.CreateDate)
                    .Take(criteriaModel.NbrItemsParPage);

这给了我一个 IEnumerable(在此处使用 umbraco),其中包含我想要的“Actualites”类型的 criteriaModel.NbrItemsParPageIPublishedContent 项目...

现在,我想为每个人创建一个新的TuileArticleModel 来提供我的result.ActualitesItems 属性(List&lt;TuileArticleModel&gt;)...

编辑:

我想我只是通过将问题暴露给你们并阅读 cmets 解决了我的问题。所以我这样做了:

 var actus = tousLesArticlesFromDb
                    .ToList()
                    .Where(
                        a => a.GetPropertyValue<IEnumerable<IPublishedContent>>("ficheArticle_typeDeContenu")
                                 .FirstOrDefault()?.Name == @EnumResources.TypeDeContenu_Actualites)
                    .Take(criteriaModel.NbrItemsParPage);

                result.Actualites.Items = actus.Select(a => {return getItem(a); }).ToList();

或在一个声明中:

  result.Actualites = new ListeArticlesModel
                {
                    Items = tousLesArticlesFromDb
                            .Where
                            (
                                a => a.GetPropertyValue<IEnumerable<IPublishedContent>>("ficheArticle_typeDeContenu")
                                         .FirstOrDefault()?.Name == @EnumResources.TypeDeContenu_Actualites
                            )
                            .OrderBy(a => a.CreateDate)
                            .Take(criteriaModel.NbrItemsParPage)
                            .Select(a => { return getItem(a); }).ToList(),
                };

【问题讨论】:

  • 我认为 minimal reproducible example 可以正确显示您拥有什么样的源数据(或足够模仿它的东西),以及您通过您的方法获得的结果以及您想要获得的结果可能会有所帮助跨度>
  • 你试过把 .ToList() 放在函数的末尾吗?
  • @A.Hasemeyer 我并列,但它返回给我一个 IEnumerable。但是我一直都做错了,无论如何...... :)
  • 您只需在 tousLesArticlesFromDb ToList 将所有数据放入内存然后查询它之后删除 .ToList() 即可,这会破坏查询的要点。删除 .ToList() 和 .FirstOrDefault 会给你一个你想要的选择语句的 iqueryable

标签: c# list linq umbraco


【解决方案1】:

先获取结果集:

var results = tousLesArticlesFromDb
    .Where
    (
        a => a.GetPropertyValue<IEnumerable<IPublishedContent>>("ficheArticle_typeDeContenu")
              .FirstOrDefault()?.Name == @EnumResources.TypeDeContenu_Actualites
    )
    .OrderBy(a => a.CreateDate)
    .Take(criteriaModel.NbrItemsParPage);

然后将其传递给新对象:

result.Actualites = new ListeArticlesModel
    {
        Items = results.ToList()
    };

或者,如果您想在一个语句中完成所有操作:

result.Actualites = new ListeArticlesModel
{
    Items = tousLesArticlesFromDb
        .Where
        (
            a => a.GetPropertyValue<IEnumerable<IPublishedContent>>("ficheArticle_typeDeContenu")
                  .FirstOrDefault()?.Name == @EnumResources.TypeDeContenu_Actualites
        )
        .OrderBy(a => a.CreateDate)
        .Take(criteriaModel.NbrItemsParPage);
        .ToList()
};      

【讨论】:

  • 谢谢,我想我找到了一个看起来像您提供的解决方案。它是否遗漏了完整声明中的某些内容?我不明白 Take(); 之间发生了什么。和 ToListe()...?
  • 我使用了您的单一声明解决方案来实现我的目的。我已经编辑了我的帖子,所以你可以看到你帮助的结果:)非常感谢!
【解决方案2】:
.ToList()

而不是

.FirstOrDefault()

还有一点需要注意的是

tousLesArticlesFromDb
                .Where( *** )
                .OrderBy(a => a.CreateDate)
                .Take(criteriaModel.NbrItemsParPage)
                .Select(
                    a => new ListeArticlesModel
                    {
                        Items = new List<TuileArticleModel>
                        {
                            // returns a TuileArticleModel 
                            getItem(a)
                        },
                    })

这将返回一个IQueryable,尚未完成任何处理,您刚刚为其创建了查询。

调用.ToList() 将执行IQueryable 并将结果作为列表返回。

【讨论】:

  • 实际上这根本不会返回 iqueryable。查看 tousLesArticlesFromDb 之后的 .ToList() ,它从 db 获取所有数据并在此之后对内存进行查询
  • @npo 哎呀,我看到了,如果我的回答,我打算把它编辑掉。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-17
  • 1970-01-01
相关资源
最近更新 更多