2016-09-13 64 views
2

我正在做一些舊的Winforms網格上的工作,我有兩個模型,我試圖扁平化並分配給DataGridView。如何扁平化嵌套的對象(LINQ)

這是我的示例模型。

public class StockItem 
{ 
    public string StockName { get; set; } 
    public int Id { get; set; } 
    public List<Warehouse> Warehouses { get; set; } 
} 

public class Warehouse 
{ 
    public string WarehouseName { get; set; } 
    public int Id { get; set; } 
} 

數據工作在一個倉庫必須先創建,然後分配給每個StockItem的方式。 A StockItem可能擁有所有的倉庫或可能只有一個倉庫。

我需要展平數據,以便網格顯示StockName,然後顯示股票項目的所有關聯倉庫。

StockCode1  Warehouse1 Warehouse2 Warehouse3 
StockCode2  Warehouse1 Warehouse2 
StockCode2  Warehouse1    Warehouse3 

我已經嘗試通過LINQ查詢要做到這一點,但只能得到每StockItem \倉庫的記錄。

+0

或許這將幫助? http://stackoverflow.com/questions/6428940/how-to-flatten-nested-objects-with-linq-expression –

+2

這不是真的扁平化,但交叉表/ pivoting –

+1

結果數據類型是什麼?是否有可能與'StockItem'關聯的可能倉庫的最大數量?我不熟悉WinForms DataGridView,因此可能會丟失某些東西,但是不必將其綁定到強類型對象的集合?看起來,可變數量的倉庫你不能這樣做。 –

回答

1

您可以通過創建實現它一個DataTable,你可以很容易地使用作爲來源f或gridview。首先添加的所有列,然後每隻股票添加倉庫:

var warehouseNames = 
    stocks 
    .SelectMany(x => x.Warehouses.Select(y => y.WarehouseName)).Distinct(); 

var dt = new DataTable(); 
dt.Columns.Add("StockCode"); 

foreach (var name in warehouseNames) 
{ 
    dt.Columns.Add(name); 
} 

foreach (var stock in stocks) 
{ 
    var row = dt.NewRow(); 
    row["StockCode"] = stock.Id; 
    foreach (var warehouse in stock.Warehouses) 
    { 
     row[warehouse.WarehouseName] = warehouse.Id; 
    } 
    dt.Rows.Add(row); 
} 

Warehouses

0

我做推薦它,但你可以使用dynamic對象來創建你想要的形狀的物體。 這樣做並不是一種常見的C#模式。這在Python或Javascript等語言中更常見。

C#是一種強類型語言,冒險進入動態對象的世界應該只有當絕對必要時被考慮(想想解析一個json blob)。我強烈認爲你重新評估你需要做的事情,並從另一個角度來處理它。

-1

這應該給你你需要什麼:

var flattened = stockItems 
    .Select(x => new { 
       StockName = x.StockName, 
       WarehouseNames = x.Warehouses 
            .Select(y => y.WarehouseName) 
            .ToList() }) 
    .ToList(); 

這將導致包含StockName項目的收集和WarehouseName字符串列表英寸添加了ToList以枚舉查詢。

對於這些樣本數據:

List<StockItem> stockItems = new List<StockItem> 
{ 
    new StockItem 
    { 
     StockName ="A", 
     Id = 1, 
     Warehouses = new List<Warehouse> 
     { 
      new Warehouse { Id = 1, WarehouseName = "x" }, 
      new Warehouse { Id = 2, WarehouseName = "y" } 
     } 
    }, 
    new StockItem 
    { 
     StockName = "B", 
     Id = 2, 
     Warehouses = new List<Warehouse> 
     { 
      new Warehouse { Id = 3, WarehouseName = "z" }, 
      new Warehouse { Id = 4, WarehouseName = "w" } 
     } 
    } 
}; 

我已經得到了以下結果:

enter image description here

0

事情是這樣的:

var availableWarehouses = new [] { 
    new Warehouse { 
     WarehouseName = "Warehouse1", 
     Id = 1 
    }, 
    new Warehouse { 
     WarehouseName = "Warehouse2", 
     Id = 2 
    }, 
    new Warehouse { 
     WarehouseName = "Warehouse3", 
     Id = 3 
    } 
}; 

var stocks = new [] { 
    new StockItem { 
     StockName = "StockCode1", 
     Id = 1, 
     Warehouses = new List<Warehouse> { availableWarehouses[0], availableWarehouses[1], availableWarehouses[2] } 
    }, 
    new StockItem { 
     StockName = "StockCode2", 
     Id = 2, 
     Warehouses = new List<Warehouse> { availableWarehouses[0], availableWarehouses[1] } 
    }, 
    new StockItem { 
     StockName = "StockCode3", 
     Id = 3, 
     Warehouses = new List<Warehouse> { availableWarehouses[0], availableWarehouses[2] } 
    } 
}; 

var flatten = stocks.Select(item => new { 
     StockName = item.StockName, 
     WarehousesNames = availableWarehouses.Select(warehouse => item.Warehouses.Contains(warehouse) ? warehouse.WarehouseName : "   ") 
      .Aggregate((current, next) => current + "\t" + next) 
    }); 

foreach(var item in flatten) { 
    Console.WriteLine("{0}\t{1}", item.StockName, item.WarehousesNames); 
}