I have the following C# method which I use to pre-load a data table of stock. Although it works very well, now I have many rows in the table, it can be very very slow to load.

Please can someone recommend a better and much faster way to do this? (Ideally to remove the "foreach" code as this is the slow bit!). 

```
public static DataTable GetProducts()
{
    DataTable table = new DataTable();

    using (DataClassesDataContext data = new DataClassesDataContext(cDbConnection.GetConnectionString()))
    {
        var query = (from p in data.Products
                     where p.Deleted == false
                     join s in data.ProductStocks on p.ProductID equals s.ProductID
                     group s by p into g
                     select new { g });

        table.Columns.Add("Barcode", typeof(string));
        table.Columns.Add("Stock Code", typeof(string));
        table.Columns.Add("Description", typeof(string));
        table.Columns.Add("Price", typeof(string));
        table.Columns.Add("Tax", typeof(string));
        table.Columns.Add("Stock", typeof(string));
        table.Columns.Add("Service Item", typeof(bool));
        table.Columns.Add("Deduct Stock", typeof(bool));

        if (query != null)
        {
            foreach (var item in query)
            {
                try
                {
                    decimal? Tax = 0;
                    if (item.g.Key.ProductTax != null)
                    {
                        Tax = Common.Utilities.IsValueValidDecimal(item.g.Key.ProductTax.TaxRate, 0);   // Tax
                    }
                    else
                    {
                        Tax = 0;
                    }

                    bool DeductStock = !Convert.ToBoolean(item.g.Key.ServiceItem);

                    string[] row = new string[] 
                    {
                        item.g.Key.EANCode.ToString(),       // Barcode
                        item.g.Key.OurStockCode.ToString(),  // Product Code
                        item.g.Key.Description.ToString(),   // desc
                        GetGUIDisplayPrice(item.g.Key.RetailPrice, item.g.Key.RetailPriceExVAT),  // cost
                        Tax.ToString(),                         // Tax   
                        item.g.Sum(s => s.QtyOnHand).ToString(), // Stock
                        item.g.Key.ServiceItem.ToString(),   // Service Item (non-stock)
                        DeductStock.ToString()                  // if not a service item, the its a stocked item so deduct!
                    };

                    table.Rows.Add(row);
                }
                catch (Exception ex)
                {
                }
            }
        }//ENDIF NULL
    }//END USING

    return table;
}

```