我使用LINQ计算了4个属性:
public decimal TotalEatin { get; set; }
public int EatinAmount { get; set; }
public decimal TotalTakeout { get; set; }
public int TakeoutAmount { get; set; }我生成值的方式是这样正确的,但是我认为代码有点麻烦,因为需要重复迭代。
因为我需要从不同的DataTables生成值,所以我不知道如何使用一个“大型”查询来改进这个查询。我对LINQ /SQL类语法的了解实在太少了。
是否有可能将这些属性放在单独的类中,并使用适当的LINQ生成具有正确属性值的该类的一个实例?
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();发布于 2019-09-18 17:45:07
如果您只需要从一组数据表中计算一些值,那么使用LINQ就足够了。但是,如果您希望提供一个包含订单和订单详细信息的通用功能的API,那么您应该真正创建自己的域类,并将数据表映射到域类。为了这个问题,我选择直接在数据表上使用LINQ。
您正在一次又一次地迭代您的3个数据表kassaOrders、orderDetails和menuDetails,每个订单细节都有一个指向kassa订单的链接,每个菜单细节都有一个指向kassa订单的链接。通过在查找集合中缓存这些表,我们可以轻松地优化性能和减少代码冗余。
首先,将kassa命令缓存到字典中的order id中(在orders中称为串行命令)。这样,快速查找就可以加入细节。
Data.kassaOrders.AsEnumerable() .Where(x => x.Field(“btw票证”)和!x.Field("terugname")和!x.Field("teruggenomen"))
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(“外卖”))
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"))
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中不存在的键。
var EatinAmount = orders
.Select(order => orderDetailsEatIn[order.Key])
.Count(details => details.Any());你的规格对我来说有点奇怪。我希望是Order 1-->* OrderDetail 1-->* MenuDetail。相反,基数是Order 1-->* OrderDetail, Order 1-->* MenuDetail,每个菜单细节的价格乘以订单详细信息的数量,以按菜单细节计算小计。
我们可以按以下方式计算订单细节的小计:
var subtotalOrderDetailEatIn = orders
.SelectMany(order => orderDetailsEatIn[order.Key])
.Select(detail => detail.Field<decimal>("price"))
.DefaultIfEmpty(0).Sum();以及菜单详细信息的小计:
var subtotalMenuDetailEatIn = orders
.SelectMany(order => orderDetailsEatIn[order.Key]
.SelectMany(detail => menuDetailsEatIn[order.Key]))
.Select(detail => detail.Field<decimal>("prijs"))
.DefaultIfEmpty(0).Sum();赠款总额为:
var TotalEatin = subtotalOrderDetailEatIn + subtotalMenuDetailEatIn;请注意,这只是使用LINQ从数据表中计算这些值的一种可能方法。其他方式可包括:
GroupJoin构建复杂类的更高级LINQ方法给出了几个扁平集合和连接选择器。这真的取决于你,看看你是多么舒适地探索LINQ的领域。
https://codereview.stackexchange.com/questions/84072
复制相似问题