This is how I solved the problem (not only the query but also CSV export):
This method returns valid CSV file:
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;
}
The below method produces IEnumerable<string>
object from data. Taken from this great thread 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())) + "\"";
}
}
Note that with the above method a valid CSV will be produced only if your object stores values in Properties as opposed to Fields.
The below is my actual data query with one Join statement. It also does some data formatting which is specific for my task but I decided to post it here too:
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();
}
}
Hope it'll help someone