通过公共外键

时间:2017-08-02 08:29:41

标签: c# sql asp.net-mvc linq entity

我在sql& linq中是个笨蛋,我一直陷入一个奇怪的问题:

我有3个表,简化如下:

+-----------+
|   Order   |
+-----------+
| ID | Name |
+-----------+

+-----------------------+
|       Ticket_01       |
+-----------------------+
| ID | Value | Order_ID |
+-----------------------+

+-----------------------+
|       Ticket_02       |
+-----------------------+
| ID | Value | Order_ID |
+-----------------------+

关系是1(订单)到多(Ticket_01)和1(订单)到多(Ticket_02) 每个订单“可能包含”,例如,2 Ticket_01和5 Ticket_02。

我有一个包含每个订单数据的类:

(简化的)

public class OrderData
{
     string orderName; 
     decimal tickets_01_ValueSumatorium;
     int numberOfTickets_01_withValueGreaterThan50;
     decimal tickets_02_ValueSumatorium;
}

所以我想按“订单”分组,使用linq,每个“Ticket_01”和“Ticket_02”。

我正在尝试这样的事情:

var list = (from Order in db.Orders
            join Ticket_01 in db.Tickets_01 on Order.ID equals Ticket_01.Order.Id
            join Ticket_02 in db.Tickets_02 on Order.ID equals Ticket_02.Order.Id
            group new {Ticket_01, Ticket_02} by Order into group
            select new OrderData
            {
                orderName = group.Key.Name,
                tickets_01_ValueSumatorium = group.Sum(t => Tickets_01.Value),
                // etc etc (filling each class field)
            }).ToList();

但是这样做,结果是重复的或三重的,或四重的,等等。我“理解”原因,但我也认为应该有一种“简单/快速”的方式来分组/合并门票具有公共外键(Order_ID)的数据。

如果没有真棒/神奇的方法来做,我想知道你的主人认为这是做这件事的好方法,因为我逐一把这些数据和savig一个接一个地合并我提到的类中的订单ID:S

谢谢大家!首先发布在这里^^。如果需要任何澄清,我会在这里。

2 个答案:

答案 0 :(得分:0)

db.Orders join db.Tickets_01 join db.Tickets_02部分使用给定订单的所有 Ticket_02s连接所有 Ticket_01s,为您提供nxm行,其中n是订单编号&#39 ; s Ticket_01s和m是其Ticket_02s的数量(这也意味着如果订单没有任何类型的票证,您将不会收到任何内容)。

您似乎想要实现的目标是:每个订单产生一个结果,并在订单的相应门票集合中汇总。

from order in db.Orders
select new
{
    Order = order,
    Tickets01 = from ticket in db.Tickets_01 where ticket.OrderId == order.ID select ticket,
    Tickets02 = from ticket in db.Tickets_02 where ticket.OrderId == order.ID select ticket
} into orderWithTickets
select new OrderData
{
    orderName = orderWithTickets.Order.Name,
    tickets_01_ValueSumatorium = orderWithTickets.Tickets01.Sum(t => t.Value),
    numberOfTickets_01_withValueGreaterThan50 = (from t in orderWithTickets.Tickets01 where t.Value > 50 select t).Sum(t => t.Value),
    // ...
};

,或等效(因为我不喜欢'因为我不喜欢查询语法):

db.Orders.Select(order => new
{
    Order = order,
    Tickets01 = db.Tickets_01.Where(ticket => ticket.OrderId == order.ID),
    Tickets02 = db.Tickets_02.Where(ticket => ticket.OrderId == order.ID)
})
.Select(orderWithTickets => new OrderData
{
    orderName = orderWithTickets.Order.Name,
    tickets_01_ValueSumatorium = orderWithTickets.Tickets01.Sum(t => t.Value),
    numberOfTickets_01_withValueGreaterThan50 = orderWithTickets.Tickets01.Where(t => t.Value > 50).Sum(t => t.Value),
    // ...
})

感觉你应该将订单的门票建模为navigation properties,在这种情况下,您只需要:

db.Orders.Select(order => new OrderData
{
    orderName=order.Name,
    tickets_01_ValueSumatorium = order.Tickets_01.Sum(t=>t.Value),
    numberOfTickets_01_withValueGreaterThan50 = order.Tickets_01.Where(t => t.Value > 50).Sum(t => t.Value)
    // ...
});

答案 1 :(得分:0)

这是你想做的吗?

List<Order> orders = new List<Order>();
orders.Add(new Order() { Id = 1, Name = "Order1" });
orders.Add(new Order() { Id = 2, Name = "Order2" });
List<Ticket1> ticket1List = new List<Ticket1>();
ticket1List.Add(new Ticket1() { Id = 10, OrderId = 1, Value = 2 });
ticket1List.Add(new Ticket1() { Id = 20, OrderId = 1, Value = 4 });
List<Ticket2> ticket2List = new List<Ticket2>();
ticket2List.Add(new Ticket2() { Id = 100, OrderId = 1, Value = 1 });
ticket2List.Add(new Ticket2() { Id = 200, OrderId = 1, Value = 3 });
ticket2List.Add(new Ticket2() { Id = 300, OrderId = 2, Value = 5 });

var sumT1 = from o in orders
            from t1 in ticket1List.Where(a => a.OrderId == o.Id).GroupBy(a => a.OrderId)
            select new { OrderId = o.Id, SumT1 = t1.Sum(a => a.Value) };

var sumT2 = from o in orders
            from t2 in ticket2List.Where(a => a.OrderId == o.Id).GroupBy(a => a.OrderId)
            select new { OrderId = o.Id, SumT2 = t2.Sum(a => a.Value) };

var list = from o in orders
           from s1 in sumT1.Where(x => x.OrderId == o.Id).DefaultIfEmpty()
           from s2 in sumT2.Where(x => x.OrderId == o.Id).DefaultIfEmpty()
           select new OrderData()
           {
               OrderName = o.Name,
               Ticket1Sum = s1?.SumT1 ?? 0,
               Ticket2Sum = s2?.SumT2 ?? 0             
           };

类:

class OrderData
{
    public string OrderName { get; set; }
    public int Ticket1Sum { get; set; }
    public int Ticket2Sum { get; set; }
}

class Order
{
    public int Id { get; set; }
    public string Name { get; set; }
}

class Ticket1
{
    public int Id { get; set; }
    public int Value { get; set; }
    public int OrderId { get; set; }
}

class Ticket2
{
    public int Id { get; set; }
    public int Value { get; set; }
    public int OrderId { get; set; }
}