Вот рабочий пример. Я сделал это в два этапа.
[Test]
public void Test333()
{
List<Order> O;
var M = Prepare333Data(out O);
var OTop = from o in O
group o by new {id=o.id, orderid=o.orderid}
into p
let topType = p.Min(tt => tt.type)
select new Order(p.Key.id, p.Key.orderid, topType);
var ljoin = from m in M
join t in OTop on m.id equals t.id into ts
from u in ts.DefaultIfEmpty()
select new {u.id, u.orderid, u.type};
}
public class Manufacturer
{
public Manufacturer(int id, string name)
{
this.id = id;
this.name = name;
}
public int id { get; set; }
public string name { get; set; }
}
public class Order
{
public Order(int id, int orderid, int type)
{
this.orderid = orderid;
this.id = id;
this.type = type;
}
public int orderid { get; set; }
public int id { get; set; }
public int type { get; set; }
}
private List<Manufacturer> Prepare333Data(out List<Order> O)
{
var M = new List<Manufacturer>() {new Manufacturer(1, "Abc"), new Manufacturer(2, "Def")};
O = new List<Order>()
{
new Order(1, 1, 2),
new Order(1, 2, 2),
new Order(1, 2, 3),
new Order(2, 3, 1)
,
new Order(2, 3, 1)
,
new Order(2, 3, 2)
};
return M;
}
ответ на комментарии:
ваш "new {" создает новый анонимный тип. Считается, что два анонимных типа, созданные разностными процессами, имеют одинаковую сигнатуру, если типы объявлены в одном и том же порядке и имеют одинаковое определение типа (то есть int соответствует int, а не int соответствует short). Я не тестировал этот сценарий в LINQ.
Вот почему я работал с реальными конкретными классами, а не с анонимными типами в части JOIN. Вероятно, есть способ переработать его с помощью чистого LINQ, но я пока не знаю, что это за . Я отправлю вам ответ, если со мной все в порядке.
Я бы посоветовал сейчас использовать конкретные классы.
то есть вместо
*new {*
при выполнении объединений всегда используйте
*new CLASSNAME(){prop1="abc",prop2="123"*
Это немного дольше, но безопаснее ... безопаснее, по крайней мере, пока мы не выясним, что происходит внутри внутренних компонентов LINQ.