1

一个相对简单的任务......我需要从数据库中提取数据并将其导出到 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 复制此查询?一般来说,完成这项任务的最佳方法是什么?

只是为了理解:主表“订单”与地址、客户、订单状态和付款表一对多链接。Table Payment 与 PaymentStatus 和 PaymentMethod 是一对多的关系。表 OrderOrderStatus 与 OrderStatus 是一对多的关系。

谢谢!

4

1 回答 1

3

这就是我解决问题的方法(不仅是查询,还有 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>从数据中生成对象。取自这个伟大的线程将对象序列化为自定义字符串格式以在输出文件中使用的最佳实践

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();
    }
}

希望它会帮助某人

于 2013-11-03T23:55:58.557 回答