一个相对简单的任务......我需要从数据库中提取数据并将其导出到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具有一对多的关系。
谢谢!
答案 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();
}
}
希望它能帮助某人