【问题标题】:EF Lambda Query - calculation for each item?EF Lambda Query - 每个项目的计算?
【发布时间】:2019-01-21 00:49:29
【问题描述】:

我正在使用服务获取项目集合。我想计算结果中每个项目与地理坐标的距离,但我不知道如何使用 lambda 将其添加到现有服务查询中。

这就是我获取数据的方式:

IEnumerable<Listing> items = await _listingService.Query(x => x.CategoryID 
        == model.CategoryID || keys.Any(c => c == x.CategoryID))
                    .Include(x => x.ListingPictures)
                    .Include(x => x.Category)
                    .SelectAsync();

这是我使用LINQ 获取距离的方式,但这是在运行上述语句后使用items 集合:

double lat = 41.2;
double lon = -71.01;
DbGeography point = DbGeography.FromText(String.Format(CultureInfo.InvariantCulture, "POINT({0} {1})", lon, lat));

List<Listing> items1 = new List<Listing>(from g in items
                          let distance = g.Geolocation.Distance(point)
                          orderby distance
                          select new Listing()
                             {
                                 ID = g.ID,                               
                                 CategoryID = g.CategoryID,
                                 Title = g.Title,
                                 Description = g.Description,
                                 Price = g.Price,
                                 Location = g.Location,
                                 Created = g.Created,
                                 DistanceInMiles = (distance / 1609.344),
                             });
    items = items1;

这不起作用,因为它丢失了第一个查询中 Include() 语句中的所有关系。我不知道如何在第一个服务 lambda 查询中使用类似 let 的关键字来做同样的事情。我试图不查询两次。有没有办法计算第一个服务查询 lambda 中的字段,以便我可以将距离添加到每个项目?

我认为使用 projections 可能有效,但我无法做到。

【问题讨论】:

  • 没有办法让它“丢失”包含,是什么让你认为正在发生这种情况?
  • @DavidG 例如,当我将_listingService.QueryInclude(x =&gt; x.ListingPictures) 一起使用时,item 集合中的每个项目都包含ListingPictures(计数>0)。在我使用let clauseselect new projection 运行第二个linq 查询后,每个item 上的ListingPictures 都是空的。似乎是有道理的,因为 selecte new 投影正在创建一个 Listing 对象,但没有为每个列表创建相关实体。
  • 我可能不得不在我的 linq 语句中使用连接或在 select new 中使用某种嵌套来保留相关的属性集合。

标签: c# entity-framework linq lambda


【解决方案1】:

items1 是一组全新的Listing 对象,您不是在“更新”现有对象的值。因此,因为您没有复制 ListingPicturesCategory 属性,所以它们将为空。你需要在你的投影中做这样的事情:

select new Listing()
{
    ID = g.ID,                               
    CategoryID = g.CategoryID,
    Title = g.Title,
    Description = g.Description,
    Price = g.Price,
    Location = g.Location,
    Created = g.Created,
    DistanceInMiles = (distance / 1609.344),
    ListingPictures = g.ListingPictures, //Add this line
    Category = g.Category //and this line
});

或者,您似乎只是在尝试更新 DistanceInMiles 属性,最好使用简单的 foreach 循环来完成。

【讨论】:

    【解决方案2】:

    我认为在这种情况下使用 linq 会降低您的语句的可读性,但以下是您的操作方法:

    List<Listing> items1 = items.Select(g => select new Listing()
                                 {
                                     ID = g.ID,                               
                                     CategoryID = g.CategoryID,
                                     Title = g.Title,
                                     Description = g.Description,
                                     Price = g.Price,
                                     Location = g.Location,
                                     Created = g.Created,
                                     DistanceInMiles = (g.Geolocation.Distance(point) / 1609.344),
                                 });
    

    【讨论】:

    • 看起来类似于我已经在使用的 linq 语句,但没有解决关系问题。我如何填充ListingPictures,因为它正在使用.Include(x =&gt; x.ListingPictures)
    • 两个查询都是 Linq 查询,你的称为查询语法,我的是 lambda 语法。 ListingPictures 已经包含在项目中,你为什么还要关心它?
    猜你喜欢
    • 2011-03-21
    • 2018-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-09
    • 2011-10-16
    • 2020-12-27
    • 1970-01-01
    相关资源
    最近更新 更多