首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >食品外卖的分组和求和值

食品外卖的分组和求和值
EN

Code Review用户
提问于 2015-03-14 10:19:59
回答 1查看 395关注 0票数 5

我使用LINQ计算了4个属性:

代码语言:javascript
复制
public decimal TotalEatin { get; set; }
public int EatinAmount { get; set; }

public decimal TotalTakeout { get; set; }
public int TakeoutAmount { get; set; }

我生成值的方式是这样正确的,但是我认为代码有点麻烦,因为需要重复迭代。

因为我需要从不同的DataTables生成值,所以我不知道如何使用一个“大型”查询来改进这个查询。我对LINQ /SQL类语法的了解实在太少了。

是否有可能将这些属性放在单独的类中,并使用适当的LINQ生成具有正确属性值的该类的一个实例?

代码语言:javascript
复制
TotalEatin = Data.kassaOrders.AsEnumerable().Where(x => x.Field<bool>("btwticket") && !x.Field<bool>("terugname") && !x.Field<bool>("teruggenomen"))
    .SelectMany(x => Data.orderDetails.AsEnumerable().Where(d => d.Field<int>("orderid") == x.Field<int>("serial") && !d.Field<bool>("takeout")))
    .Sum(x => x.Field<decimal>("price"));

TotalEatin += Data.kassaOrders.AsEnumerable().Where(x => x.Field<bool>("btwticket") && !x.Field<bool>("terugname") && !x.Field<bool>("teruggenomen"))
    .SelectMany(x => Data.orderDetails.AsEnumerable().Where(d => d.Field<int>("orderid") == x.Field<int>("serial") && !d.Field<bool>("takeout")))
    .SelectMany(x => Data.MenuDetails.AsEnumerable().Where(d => d.Field<int>("orderid") == x.Field<int>("orderid")))
    .Sum(x => x.Field<decimal>("prijs"));

EatinAmount = Data.kassaOrders.AsEnumerable().Where(x => x.Field<bool>("btwticket") && !x.Field<bool>("terugname") && !x.Field<bool>("teruggenomen"))
    .SelectMany(x => Data.orderDetails.AsEnumerable().Where(d => d.Field<int>("orderid") == x.Field<int>("serial") && !d.Field<bool>("takeout")))
    .GroupBy(x => new { takeout = x.Field<bool>("takeout"), orderid = x.Field<int>("orderid") }).Distinct().Count();

TotalTakeout = Data.kassaOrders.AsEnumerable().Where(x => x.Field<bool>("btwticket") && !x.Field<bool>("terugname") && !x.Field<bool>("teruggenomen"))
    .SelectMany(x => Data.orderDetails.AsEnumerable().Where(d => d.Field<int>("orderid") == x.Field<int>("serial") && d.Field<bool>("takeout")))
    .Sum(x => x.Field<decimal>("price"));

TotalTakeout += Data.kassaOrders.AsEnumerable().Where(x => x.Field<bool>("btwticket") && !x.Field<bool>("terugname") && !x.Field<bool>("teruggenomen"))
    .SelectMany(x => Data.orderDetails.AsEnumerable().Where(d => d.Field<int>("orderid") == x.Field<int>("serial") && d.Field<bool>("takeout")))
    .SelectMany(x => Data.MenuDetails.AsEnumerable().Where(d => d.Field<int>("orderid") == x.Field<int>("orderid")))
    .Sum(x => x.Field<decimal>("prijs"));

TakeoutAmount = Data.kassaOrders.AsEnumerable().Where(x => x.Field<bool>("btwticket") && !x.Field<bool>("terugname") && !x.Field<bool>("teruggenomen"))
    .SelectMany(x => Data.orderDetails.AsEnumerable().Where(d => d.Field<int>("orderid") == x.Field<int>("serial") && d.Field<bool>("takeout")))
    .GroupBy(x => new { takeout = x.Field<bool>("takeout"), orderid = x.Field<int>("orderid") }).Distinct().Count();
EN

回答 1

Code Review用户

发布于 2019-09-18 17:45:07

范围

如果您只需要从一组数据表中计算一些值,那么使用LINQ就足够了。但是,如果您希望提供一个包含订单和订单详细信息的通用功能的API,那么您应该真正创建自己的域类,并将数据表映射到域类。为了这个问题,我选择直接在数据表上使用LINQ。

评论

您正在一次又一次地迭代您的3个数据表kassaOrdersorderDetailsmenuDetails,每个订单细节都有一个指向kassa订单的链接,每个菜单细节都有一个指向kassa订单的链接。通过在查找集合中缓存这些表,我们可以轻松地优化性能和减少代码冗余。

查找表

首先,将kassa命令缓存到字典中的order id中(在orders中称为串行命令)。这样,快速查找就可以加入细节。

Data.kassaOrders.AsEnumerable() .Where(x => x.Field(“btw票证”)和!x.Field("terugname")和!x.Field("teruggenomen"))

代码语言:javascript
复制
 var orders = Data.kassaOrders
    .AsEnumerable()
    .Where(x => 
         x.Field<bool>("btwticket") && 
        !x.Field<bool>("terugname") && 
        !x.Field<bool>("teruggenomen"))
    .ToDictionary(order => order.Field<int>("serial"));

然后,我们可以使用查找表--它们是存储值序列而不是值的字典--通过order id缓存顺序和菜单细节。这段代码展示了如何在里面吃东西,可以编写等效的LINQ以便取出。

Data.orderDetails.AsEnumerable() .Where(d => d.Field("orderid") == x.Field(“串行”)&!d.Field(“外卖”))

代码语言:javascript
复制
 var orderDetailsEatIn = Data.orderDetails
    .Where(order => !order.Field<bool>("takeout"))
    .ToLookup(detail => detail.Field<int>("orderid"));

Data.MenuDetails.AsEnumerable() .Where(d => d.Field("orderid") == x.Field("orderid"))

代码语言:javascript
复制
var menuDetailsEatIn = Data.MenuDetails
   .Where(order => !order.Field<bool>("takeout"))
   .ToLookup(detail => detail.Field<int>("orderid"));

计算量

你在用一个特殊的GroupBy来计算数量。没有理由按取出变量分组,因为您在!d.Field<bool>("takeout")之前筛选特定的值。对Distinct的调用也没有意义,因为细节已经按键分组,而且键也是不同的。

GroupBy(x =>新的{.Count=x.Field(外卖),orderid = x.Field (Orderid) }).Distinct().Count();

使用我们的查找表,我们可以轻松地计算出如下所示的金额。为了保持在您的规范范围内,我们将统计至少有一个订单细节可用的订单数量。请注意,返回空集合时,orderDetailsEatIn[key]ILookup中不存在的键。

代码语言:javascript
复制
 var EatinAmount = orders
    .Select(order => orderDetailsEatIn[order.Key])
    .Count(details => details.Any());

计算总

你的规格对我来说有点奇怪。我希望是Order 1-->* OrderDetail 1-->* MenuDetail。相反,基数是Order 1-->* OrderDetail, Order 1-->* MenuDetail,每个菜单细节的价格乘以订单详细信息的数量,以按菜单细节计算小计。

我们可以按以下方式计算订单细节的小计:

代码语言:javascript
复制
var subtotalOrderDetailEatIn = orders
    .SelectMany(order => orderDetailsEatIn[order.Key])
    .Select(detail => detail.Field<decimal>("price"))
    .DefaultIfEmpty(0).Sum();

以及菜单详细信息的小计:

代码语言:javascript
复制
var subtotalMenuDetailEatIn = orders
    .SelectMany(order => orderDetailsEatIn[order.Key]
        .SelectMany(detail => menuDetailsEatIn[order.Key]))
    .Select(detail => detail.Field<decimal>("prijs"))
    .DefaultIfEmpty(0).Sum();

赠款总额为:

代码语言:javascript
复制
var TotalEatin = subtotalOrderDetailEatIn + subtotalMenuDetailEatIn;

请注意,这只是使用LINQ从数据表中计算这些值的一种可能方法。其他方式可包括:

  • 创建中间类、值元组或域类来存储强类型属性,以便于查询可读性。
  • 使用GroupJoin构建复杂类的更高级LINQ方法给出了几个扁平集合和连接选择器。

这真的取决于你,看看你是多么舒适地探索LINQ的领域。

票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/84072

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档