C# 通过公共外键合并表字段

C# 通过公共外键合并表字段,c#,sql,asp.net-mvc,linq,entity,C#,Sql,Asp.net Mvc,Linq,Entity,我是sql&linq的乞丐,我一直陷入一个奇怪的问题: 我有3张表,它们看起来像: +-----------+ | Order | +-----------+ | ID | Name | +-----------+ +-----------------------+ | Ticket_01 | +-----------------------+ | ID | Value | Order_ID | +-----------------------+ +-----

我是sql&linq的乞丐,我一直陷入一个奇怪的问题:

我有3张表,它们看起来像:

+-----------+ | Order | +-----------+ | ID | Name | +-----------+ +-----------------------+ | Ticket_01 | +-----------------------+ | ID | Value | Order_ID | +-----------------------+ +-----------------------+ | Ticket_02 | +-----------------------+ | ID | Value | Order_ID | +-----------------------+ 因此,我想使用linq,通过“订单”,对每个“票证01”和“票证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)的票据数据

如果没有awesom/magic方法可以做到这一点,我想知道您认为哪种方法是最好的方法,因为我正在一个接一个地获取数据,并通过在我提到的类中保存Order ID来一个接一个地合并它:S


谢谢大家!第一篇文章在这里^^。如果需要澄清,我会在这里的

db.Orders join db.Tickets\u 01 join db.Tickets\u 02部分将所有Ticket\u 01与给定订单的所有Ticket\u 02连接起来,给出n x m行,其中n是订单的Ticket\u 01的编号,m是其Ticket\u 02的编号(这也意味着如果订单没有任何一种类型的Ticket,您将不会收到任何东西)

您似乎试图实现的是:每个订单一个结果,并对订单各自的票证集合进行聚合

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 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)
    // ...
});

db.Orders join db.Tickets\u 01 join db.Tickets\u 02
部分将所有Ticket\u 01与给定订单的所有Ticket\u 02连接在一起,给出n x m行,其中n是订单的Ticket\u 01的编号,m是其Ticket\u 02的编号(这也意味着如果订单没有任何一种类型的Ticket,您将不会收到任何东西)

您似乎试图实现的是:每个订单一个结果,并对订单各自的票证集合进行聚合

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 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)
    // ...
});

这就是你想做的吗

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             
           };

这就是你想做的吗

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             
           };

嗯,是的,但是我试图避免创建那么多的列表。不管怎样,你的答案看起来比我执行的答案好,谢谢。顺便问一下,一个小问题:->这个语法是如何调用的?“Ticket1Sum=s1?.SumT1±0”?是空条件运算符,并且??是空合并运算符。是的,但我试图避免创建那么多列表。不管怎样,你的答案看起来比我执行的答案好,谢谢。顺便问一下,一个小问题:->这个语法是如何调用的?“Ticket1Sum=s1?.SumT1±0”?是空条件运算符,并且??是空合并运算符。它看起来像是我搜索的那种“技巧”!现在就实现它,如果我想要的话就编辑评论。这看起来就像是我搜索的那种“把戏”!现在就实现它,如果我想做的话就编辑评论。