通过公共外键合并 table 个字段
Merging table fields by common foreign key
我是sql&linq的新手,一直卡在一个奇怪的问题中:
我有 3 个表,简化后的样子:
+-----------+
| Order |
+-----------+
| ID | Name |
+-----------+
+-----------------------+
| Ticket_01 |
+-----------------------+
| ID | Value | Order_ID |
+-----------------------+
+-----------------------+
| Ticket_02 |
+-----------------------+
| ID | Value | Order_ID |
+-----------------------+
关系是 1(顺序)对多(Ticket_01)和 1(顺序)对多(Ticket_02)
其中每个订单 "may contain",例如 2 Ticket_01 和 5 Ticket_02.
我有一个 class,其中包含每个订单的数据:
(简体)
public class OrderData
{
string orderName;
decimal tickets_01_ValueSumatorium;
int numberOfTickets_01_withValueGreaterThan50;
decimal tickets_02_ValueSumatorium;
}
所以我想按 "Order" 分组,使用 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();
但这样做,结果会重复或三次,或四次,等等。我"understand"原因,但我也认为应该有一种“"easy/fast"”的方式来group/merge 具有公共外键 (Order_ID) 的票据数据。
如果没有awesom/magic的方法,我想知道各位高手认为哪种方法比较好,因为我是一个一个的gettig数据,一个一个的合并通过在我提到的 class 中保存订单 ID,逐个保存:S
谢谢大家!先post这里^^。如果需要任何说明,我会在这里。
db.Orders join db.Tickets_01 join db.Tickets_02
部分将给定订单的allTicket_01s与allTicket_02s连接起来,给你 n x m 行,其中 n 是订单的 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)
// ...
});
这是你想做的吗?
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; }
}
我是sql&linq的新手,一直卡在一个奇怪的问题中:
我有 3 个表,简化后的样子:
+-----------+ | Order | +-----------+ | ID | Name | +-----------+ +-----------------------+ | Ticket_01 | +-----------------------+ | ID | Value | Order_ID | +-----------------------+ +-----------------------+ | Ticket_02 | +-----------------------+ | ID | Value | Order_ID | +-----------------------+
关系是 1(顺序)对多(Ticket_01)和 1(顺序)对多(Ticket_02) 其中每个订单 "may contain",例如 2 Ticket_01 和 5 Ticket_02.
我有一个 class,其中包含每个订单的数据:
(简体)
public class OrderData
{
string orderName;
decimal tickets_01_ValueSumatorium;
int numberOfTickets_01_withValueGreaterThan50;
decimal tickets_02_ValueSumatorium;
}
所以我想按 "Order" 分组,使用 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();
但这样做,结果会重复或三次,或四次,等等。我"understand"原因,但我也认为应该有一种“"easy/fast"”的方式来group/merge 具有公共外键 (Order_ID) 的票据数据。
如果没有awesom/magic的方法,我想知道各位高手认为哪种方法比较好,因为我是一个一个的gettig数据,一个一个的合并通过在我提到的 class 中保存订单 ID,逐个保存:S
谢谢大家!先post这里^^。如果需要任何说明,我会在这里。
db.Orders join db.Tickets_01 join db.Tickets_02
部分将给定订单的allTicket_01s与allTicket_02s连接起来,给你 n x m 行,其中 n 是订单的 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)
// ...
});
这是你想做的吗?
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; }
}