实体框架 - 复杂查询 - 和CSV导出

时间:2013-11-03 02:34:23

标签: c# linq entity-framework csv sql-to-linq-conversion

一个相对简单的任务......我需要从数据库中提取数据并将其导出到CSV文件。问题是从几个连接表中查询数据,我不确定使用EF获取数据并将其序列化的最佳方法是什么。

我的SQL查询是:

select o.product, o.invoicenr, o.amount as quantity, o.price, o.shipping, o.vatrate, o.datecreated, os.title as [orderstatus],ps.title as [paymentstatus], pm.title as [paymentmethod], o.datepaid, o.dateinvoice,
c.*, a.*,
oos.trackingcode, oos.courier, oos.datecreated as [orderstatusdate],
 p.amout, p.transactionIdentifier, p.comment, p.datecreated as [paymentcreated]
 from [order] o
    inner join Address a
        on o.shipingaddressId = a.id
    inner join Customer c
        on o.customerId = c.id
    inner join OrderOrderStatus oos
        inner join OrderStatus os
         on oos.orderstatusId = os.id
         on o.id = oos.orderID      
    inner join Payment p 
        inner join PaymentStatus ps
         on p.paymentstatusId = ps.id
        inner join PaymentMethod pm
         on p.paymentmethodId = pm.id
        on o.id = p.orderId
order by o.datecreated, o.id

组合后,应该返回44列。

如何使用LINQ复制此查询?一般来说,完成此任务的最佳方法是什么?

只是为了理解:主表“订单”与表格Address,Customer,OrderOrderStatus和Payment一对多地链接。表格付款与PaymentStatus和PaymentMethod具有一对多的关系。表OrderOrderStatus与OrderStatus具有一对多的关系。

谢谢!

1 个答案:

答案 0 :(得分:1)

这就是我解决问题的方法(不仅是查询,还包括CSV导出):

此方法返回有效的CSV文件:

public string GetCSV(DateTime startDate, DateTime endDate, string separator = ",")
{
    var data = this.GetData(startDate, endDate);
    var csvData = this.ToCsv("\"" + separator + "\"", data);
    var result = string.Join(Environment.NewLine, csvData);

    return result;
}

以下方法从数据中生成IEnumerable<string>个对象。取自这个伟大的线程Best practices for serializing objects to a custom string format for use in an output file

public IEnumerable<string> ToCsv<T>(string separator, IEnumerable<T> objectlist)
{
    PropertyInfo[] properties = typeof(T).GetProperties();
    yield return "\"" + String.Join(separator, properties.Select(f => f.Name).ToArray()) + "\"";
    foreach (var o in objectlist)
    {
        yield return "\"" + HttpUtility.HtmlDecode(string.Join(separator, properties.Select(f => (f.GetValue(o) ?? "").ToString()).ToArray())) + "\"";
    }
}

请注意,使用上述方法时,只有当对象将值存储在“属性”而不是“字段”中时,才会生成有效的CSV。

以下是我的实际数据查询和一个Join语句。它还做了一些特定于我的任务的数据格式,但我也决定在这里发布:

private IEnumerable<Models.DataExport> GetData(DateTime startDate, DateTime endDate)
{
    using (var db = new DAL.smigEntities())
    {
        CultureInfo deDE = CultureInfo.CreateSpecificCulture("de-DE");

        return db.Order
            .Where(x => x.datecreated >= startDate && x.datecreated <= endDate).AsEnumerable()
            .Join(db.Payment, Order => Order.id, Payment => Payment.orderId, (Order, Payment) => new Models.DataExport
            {
                Id = Order.id,
                Product = Order.product,
                Invoicenr = Order.invoicenr,
                Quantity = string.Format("{0:0}", Order.amount),
                Price = string.Format(deDE, "{0:0.00}", Order.price),
                Shipping = string.Format(deDE, "{0:0.00}", Order.shipping),
                Vatrate = string.Format(deDE, "{0:0.00}", Order.vatrate),
                Datecreated = Order.datecreated,
                Datepaid = Order.datepaid,
                Dateinvoice = Order.dateinvoice,
                Paymentrecorddate = Payment.datecreated,
                Paymentstatus = Payment.PaymentStatus.title,
                Paymentmethod = Payment.PaymentMethod.title,
                Paidamount = string.Format(deDE, "{0:0.00}", Payment.amout),
                Transactionidentifier = Payment.transactionIdentifier,
                Comment = Payment.comment,
                Title = Order.Address.title,
                Name = Order.Address.name,
                Lastname = Order.Address.lastname,
                Recepient2 = Order.Address.recepient2,
                Company = Order.Address.company,
                Address1 = Order.Address.address1,
                Address2 = Order.Address.address2,
                Address3 = Order.Address.address3,
                Town = Order.Address.town,
                Postcode = Order.Address.postcode,
                County = Order.Address.county,
                Country = Order.Address.country,
                Email = Order.Customer.email,
                Balancerelevant = Payment.PaymentStatus.balancerelevant.Value
            })
            .OrderByDescending(x => x.Datecreated).ThenByDescending(x => x.Id).ThenByDescending(x => x.Paymentrecorddate)
            .ToList();
    }
}

希望它能帮助某人