LINQ to DataSet查询帮助

时间:2011-07-23 06:20:06

标签: c# .net linq datatable dataset

我是LINQ的新手,所以我希望有人可以帮助我。我有一个数据库,我需要运行一个大型查询,但它是一个非常古老的ODBC驱动程序,并需要很长时间来响应(即使是一个简单的查询,30 + min)。将所有数据转储到数据集中只需要大约2-3分钟,但是我认为这是最好的,然后我可以运行LINQ to Dataset查询。我似乎无法让查询工作,我有点困惑。我将所有数据放入SQL Express数据库以测试LINQ to SQL查询,以确保我走的正确路径。我没有运行应用程序的选项,因为环境总是不同的。

SQL:

SELECT Invoice_detail.Code, Invoice_detail.Description, Product_master.Comment AS Packing, Invoice_detail.QtyInv AS INV, Invoice_detail.QtyBackOrder AS BO, Alternate_product_codes.MasterBarCode AS BarCode, Invoice_detail.PriceAmt AS Price, Invoice_detail.DiscPerc AS Disc, ROUND(Invoice_detail.TaxableAmt/Invoice_detail.QtyInv,2) AS Nett FROM ((Invoice_detail INNER JOIN Product_master ON Invoice_detail.Code = Product_master.Code) INNER JOIN Invoice_header ON Invoice_detail.InternalDocNum = Invoice_header.InternalDocNum AND Invoice_detail.DocType = Invoice_header.DocType) LEFT JOIN Alternate_product_codes ON Invoice_detail.Code = Alternate_product_codes.Code WHERE Invoice_header.DocNum = '{0}' AND Invoice_header.DocType = 1 AND Invoice_detail.LineType = 1 AND Invoice_detail.QtyInv > 0

LINQ to SQL:

from detail in INVOICE_DETAILs
join prodmast in PRODUCT_MASTERs on detail.Code equals prodmast.Code
join header in INVOICE_HEADERs on new { detail.InternalDocNum, detail.DocType } equals new { header.InternalDocNum, header.DocType}
join prodcodes in ALTERNATE_PRODUCT_CODES on detail.Code equals prodcodes.Code into alt_invd
from prodcodes in alt_invd.DefaultIfEmpty()
where
  header.DocType == 1 &&
  detail.LineType == 1 &&
  detail.QtyInv > 0 &&
  header.Date > DateTime.Parse("17/07/2011").Date &&
  header.DocNum.Trim() == "119674"
select new {
  detail.Code,
  detail.Description,
  Packing = prodmast.Comment,
  INV = detail.QtyInv,
  BO = detail.QtyBackOrder,
  Barcode = prodcodes.MasterBarCode, 
  Price = detail.PriceAmt, 
  Disc = detail.DiscPerc,
  Nett = Math.Round(Convert.ToDecimal(detail.TaxableAmt/detail.QtyInv),2,MidpointRounding.AwayFromZero)
}

LINQ to Dataset:

var query = from detail in ds.Tables["Invoice_detail"].AsEnumerable()
join prodmast in ds.Tables["Product_master"].AsEnumerable() on detail["Code"] equals prodmast["Code"]
join header in ds.Tables["Invoice_header"].AsEnumerable() on new { docnum = detail["InternalDocNum"], doctype = detail["DocType"] } equals new { docnum = header["InternalDocNum"], doctype = header["DocType"] }
join prodcodes in ds.Tables["Alternate_product_codes"].AsEnumerable() on detail["Code"] equals prodcodes["Code"] into alt_invd
from prodcodes in alt_invd.DefaultIfEmpty()
where
  (int)header["DocType"] == 1 &&
  (int)detail["LineType"] == 1 &&
  (int)detail["QtyInv"] > 0 &&
  //header.Field<DateTime>("Date") > DateTime.Parse("17/07/2011").Date &&
  header.Field<DateTime>("Date") > DateTime.Now.Date.AddDays(-7) &&
  header.Field<string>("DocNum").Trim() == "119674"
select new
{
    Code = detail["Code"],
    Description = detail["Description"],
    Packing = prodmast["Comment"],
    INV = detail["QtyInv"],
    BO = detail["QtyBackOrder"],
    Barcode = prodcodes["MasterBarCode"],
    Price = detail["PriceAmt"],
    Disc = detail["DiscPerc"],
    Nett = Math.Round(Convert.ToDecimal((double)detail["TaxableAmt"] / (int)detail["QtyInv"]), 2, MidpointRounding.AwayFromZero)
};

我需要运行LINQ to DataSet查询,然后将结果放入DataTable中,以便我可以导出为CSV。该查询将返回许多行,因此我可以看到CopyToDataTable方法,但这似乎不起作用,除非它是一个类型化的数据集。我正在使用ODBC数据适配器填充方法,因此没有专门设置我正在填充的数据表上的数据类型。原因是这些表中有很多列并且将它们全部设置起来会非常耗时。

LINQ是最好的选择吗?我接近了吗?我是否必须为所有列和数据类型设置DataTables?我能想到的唯一另一种方法是每次将数据转储到访问数据库并从那里进行查询。我更好奇让LINQ工作,因为我觉得这对我来说会更有利。

感谢任何帮助或指示。

感谢。

皮特。

2 个答案:

答案 0 :(得分:1)

考虑使用POCO对象而不是DataSet。

Blogs @ MSDN

答案 1 :(得分:0)

如果我理解正确,Linq To Dataset查询将检索正确的信息,但您无法将信息导出到csv。

如果这只是一个csv文件,您只需要使用示例中的九个字段进行创建,您就可以使用csv库(例如FileHelpers)来导出信息。

为了举例说明所涉及的额外工作,您需要定义一个类,例如

[DelimitedRecord(",")] 
public class Info
{ 
    [FieldQuoted()] 
    public string Code ;
    [FieldQuoted()] 
    public string Description ;
    [FieldQuoted()] 
    public string Packing ; 
    public decimal INV ;
    public decimal BO ;
    [FieldQuoted()] 
    public string Barcode ;
    public decimal Price ; 
    public decimal Disc ;
    public decimal Nett ;

} 

(注意,我猜的是一些字段类型)

然后,您将查询更改为使用信息,即

select new Info {
    Code = detail["Code"],
 ...

最后

    FileHelperEngine engine = new FileHelperEngine(typeof(Info)); 
    engine.WriteFile(".\\outputfile.csv", query);

你已经完成了。