I Have the following query but its not allowing me to select the properties of my custom class for some reason.
This is my class here:
public class PersonalDetails
{
public string LineType { get; set; }
public string EnquirerTitle { get; set; }
public string ForeName { get; set; }
public string Surname { get; set; }
public int Age { get; set; }
public DateTime Dob { get; set; }
public string MaritalStatus { get; set; }
public string HomePhone { get; set; }
public string MobilePhone { get; set; }
public string Email { get; set; }
public string Address { get; set; }
public string Employment { get; set; }
public string Occupation { get; set; }
}
And here I want to use a query to access the data my end goal is to pass this object to a csv selrilizer which I have created to produce a csv file in a custom format.
IQueryable<tblapertureNetAppointment> _personadetails;
var personalDetails = from _appointments in _dal.apertureNetEntities.tblapertureNetAppointments
.AsEnumerable()
.Select(x => new PersonalDetails { x.LineType its not allowing me to find line type})
.ToList();
Try this way -
var personalDetails = (from _appointments in _dal.apertureNetEntities.tblapertureNetAppointments.AsEnumerable()
select new PersonalDetails {
LineType = _appointments.LineType,
EnquirerTitle = _appointments.EnquirerTitle,
ForeName = _appointments.ForeName,
Surname = _appointments.Surname,
// .......
}).ToList();
Update
Using LinqToCsv you can write csv file from your linq object. LinqToCsv is available as nuget package.
From Package Manager Console -
Install-Package LinqToCsv
Now you can write your linq object to csv file this way -
CsvFileDescription outputFileDescription = new CsvFileDescription
{
SeparatorChar = '\t', // tab delimited
FirstLineHasColumnNames = true,
FileCultureName = "nl-NL" // use formats used in The Netherlands
};
CsvContext cc = new CsvContext();
string fileName = String.Format(#"{0}products2.csv", Server.MapPath("/csvFiles"));
cc.Write(personalDetails,fileName,outputFileDescription);
Related
I have a list of class Contact that are read from a CSV file. I want to append a record to that and eventually write it out as a new file.
The CSV is read into a List of Contact called records.
If I add a breakpoint at the line that reads records.Append(cCust); and then step over it with watches on records and cCust, I can see that records contains the CSV data and that cCust contains the data to append, but as I step over the append, nothing happens; no errors and no additional record in the records list.
What am I doing wrong?
Here's the offending code:
private void Btn_Merge_Click(object sender, EventArgs e)
{
IEnumerable<Contact> records;
IEnumerable<dynamic> MondayRows;
// Read the CSV into 'records'
StreamReader Shopifyreader = new StreamReader(textBox_Shopify.Text);
using (var ShopifyCSV = new CsvReader(Shopifyreader, CultureInfo.InvariantCulture))
{
records = ShopifyCSV.GetRecords<Contact>().ToList();
}
// Test adding a new record
Contact cCust = new Contact();
cCust.First_Name = "";
cCust.Last_Name = "";
cCust.Email = "Hello.World#business.com";
cCust.Accepts_Email_Marketing = "";
cCust.Company = "";
cCust.Address1 = "";
cCust.Address2 = "";
cCust.City = "";
cCust.Province = "";
cCust.Province_Code = "";
cCust.Country = "";
cCust.Country_Code = "";
cCust.Zip = "";
cCust.Phone = "";
cCust.Accepts_SMS_Marketing = "";
cCust.Total_Spent = "";
cCust.Total_Orders = "";
cCust.Tags = "Send me Lead Marketing";
cCust.Note = "";
cCust.Tax_Exempt = "";
records.Append(cCust);
// We can now write out the modified file
using (var writer = new StreamWriter(#"C:\temp\Output.csv"))
using (var outputCSV = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
outputCSV.WriteRecords(records);
}
}
public class Contact
{
[Name("First Name")] // This 'attribute' allows the class property First_Name to be matched to the CSV header "First Name"
public string First_Name { get; set; }
[Name("Last Name")]
public string Last_Name { get; set; }
public string Email { get; set; }
[Name("Accepts Email Marketing")]
public string Accepts_Email_Marketing { get; set; }
public string Company { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string Province { get; set; }
[Name("Province Code")]
public string Province_Code { get; set; }
public string Country { get; set; }
[Name("Country Code")]
public string Country_Code { get; set; }
public string Zip { get; set; }
public string Phone { get; set; }
[Name("Accepts SMS Marketing")]
public string Accepts_SMS_Marketing { get; set; }
[Name("Total Spent")]
public string Total_Spent { get; set; }
[Name("Total Orders")]
public string Total_Orders { get; set; }
public string Tags { get; set; }
public string Note { get; set; }
[Name("Tax Exempt")]
public string Tax_Exempt { get; set; }
}
}
This is the problem:
records.Append(cCust);
That's a LINQ extension method, which returns a sequence containing the original sequence and the new value afterwards. It doesn't modify the existing sequence.
So you could use:
records = records.Append(cCust);
However, I'd suggest changing the declared type of records to List<Contact> and then calling the Add method to add directly into the list:
records.Add(cCust);
I have a stored proc returning a datatable using a stored procedure. I am able to convert the it to an object using the following code
outgoingPaymentData.AsEnumerable().Select(x => new OutgoingPaymentApprovalDetails() { });
Here is my OutgoingPaymentApprovalDetails class
public class OutgoingPaymentApprovalDetails
{
public int OriginatorId { get; set; }
public string Name { get; set; }
public string DocumentId { get; set; }
public string DebtorName { get; set; }
public string Currency { get; set; }
public double Amount { get; set; }
public string Description { get; set; }
public string DebitAccountNo { get; set; }
public string CreditAccountNo { get; set; }
}
Now, instead of a flat list, I need to add heirarchy, to select this one object to 3 objects.
Classes as under:
public class OriginatorDetails
{
public int OriginatorId { get; set; }
public string Name { get; set; }
public List<DocumentDetails> DocumentDetails { get; set; }
}
public class DocumentDetails
{
public string DocumentId { get; set; }
public List<TransactionDetails> TransactionDetails { get; set; }
}
public class TransactionDetails
{
public string Amount { get; set; }
public string DebitAccountNo { get; set; }
public string CreditAccountNo { get; set; }
}
Basically, All Documents of a particular Originator have to be in the list of DocumentDetails and all TransactionDetails of a particular document have to be in that list.
One way is to create a dictionary and add stuff in it and finally create an object. I was wondering if there was a more abbreviated and efficient way to do something like this.
TIA
You can do the grouping of retrieved records of OutgoingPaymentApprovalDetails using Linq to create the nested object of OriginatorDetails collection.
see below code
var originalDetails = inputs.GroupBy(g => g.OriginatorId)
.Select(g => new OriginatorDetails()
{
OriginatorId = g.Key,
Name = g.First().Name,
DocumentDetails = g.GroupBy(d => d.DocumentId)
.Select(d => new DocumentDetails()
{
DocumentId = d.Key,
TransactionDetails = d.Select(t => new TransactionDetails()
{
DebitAccountNo = t.DebitAccountNo,
CreditAccountNo = t.CreditAccountNo,
Amount = t.Amount.ToString()
}).ToList()
})
.ToList()
});
Check the created https://dotnetfiddle.net/FCA7Qc to demostrate your scenario.
Try this code:
Basically you need to group 2 times, first time by OriginatorId and Name and then by DocumentId like this:
var result = list.GroupBy(c => new {c.OriginatorId, c.Name})
.Select(g => new OriginatorDetails()
{
Name = g.Key.Name,
OriginatorId = g.Key.OriginatorId,
DocumentDetails = g
.GroupBy(dd => dd.DocumentId)
.Select(dd => new DocumentDetails()
{
DocumentId = dd.Key,
TransactionDetails = dd.ToList()
.Select(td => new TransactionDetails()
{
Amount = td.Amount.ToString(),
CreditAccountNo = td.CreditAccountNo,
DebitAccountNo = td.DebitAccountNo
}).ToList()
}).ToList()
}).ToList();
I processing a soap response which the xml has a purchase order within items
eg
<PurchaseOrder>
<WHID>2</WHID>
<Supplier_ID>00</Supplier_ID>
<POID>6</POID>
<CreateDate>2013-01-02T10:48:27.37+11:00</CreateDate>
<CurrencyName>Australian Dollars</CurrencyName>
<ShippingStatus>Departed</ShippingStatus>
<payment_terms></payment_terms>
<shipping_terms></shipping_terms>
<POStatus>Back-Order</POStatus>
<PurchaseOrderItems>
<PurchaseOrderItem>
<SKU>Shoe30</SKU>
<Product_ID>124064</Product_ID>
<QtyOrdered>9</QtyOrdered>
<QtyOutstanding>6</QtyOutstanding>
<BuyPriceEx>20.0000</BuyPriceEx>
<DirectCosts>0.0000</DirectCosts>
<SupplierBuyPrice>20.0000</SupplierBuyPrice>
</PurchaseOrderItem>
</PurchaseOrderItems>
</PurchaseOrder>
I have no issues putting this into a jagged list . my classes look like this
public class PurchaseOrder
{
public string WHID { get; set; }
public string Supplier_ID { get; set; }
public string POID { get; set; }
public string CreateDate { get; set; }
public string CurrencyName { get; set; }
public string ShippingStatus { get; set; }
public string payment_terms { get; set; }
public string shipping_terms { get; set; }
public string POStatus { get; set; }
public List<PurchaseOrderItems> PurchaseOrderItems { get; set; }
}
public class PurchaseOrderItems
{
public string SKU { get; set; }
public string Product_ID { get; set; }
public string QtyOrdered { get; set; }
public string QtyOutstanding { get; set; }
public string BuyPriceEx { get; set; }
public string DirectCosts { get; set; }
public string SupplierBuyPrice { get; set; }
}
I fill the purchase order class using the following linq
List<PurchaseOrder> _orderDetailed = items.Select(po => new PurchaseOrder()
{
WHID = (string)po.Element("WHID").ElementValueNull(),
Supplier_ID = (string)po.Element("Supplier_ID").ElementValueNull(),
POID = (string)po.Element("POID").ElementValueNull(),
CreateDate = (string)po.Element("CreateDate").ElementValueNull(),
CurrencyName = (string)po.Element("CurrencyName").ElementValueNull(),
payment_terms = (string)po.Element("payment_terms").ElementValueNull(),
shipping_terms = (string)po.Element("shipping_terms").ElementValueNull(),
POStatus = (string)po.Element("POStatus").ElementValueNull(),
PurchaseOrderItems = po.Descendants("PurchaseOrderItem").Select(i => new PurchaseOrderItems()
{
SKU = (string)i.Element("SKU").ElementValueNull(),
Product_ID = (string)i.Element("Product_ID").ElementValueNull(),
QtyOrdered = (string)i.Element("QtyOrdered").ElementValueNull()
}).ToList()
}).ToList();
The problem come when I pass this to a reflection function that write the object to csv. it only writes the PurchaseOrder fields to the file. I have no idea how to access the PurchaseOrderItems fields so I can write them to the file.
I need to achieve the following using the above xml structure.
WHID Supplier_ID POID SKU Product_ID QtyOrdered
2 00 6 Shoe30 124064 6
I have cut down the fields above just to keep it easy to read. but the goal is to have all the line items and the purchase order header details on the one line.
public void WriteCSV<T>(IEnumerable<T> items, string path)
{
Type itemType = typeof(T);
var props = itemType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.OrderBy(p => p.Name);
using (var writer = new StreamWriter(path))
{
writer.WriteLine(string.Join(fieldDelimiter, props.Select(p => p.Name)));
foreach (var item in items)
{
writer.WriteLine(string.Join(fieldDelimiter, props.Select(p => p.GetValue(item, null))));
}
}
}
I know I am missing how object work here so looking for some direction.
Much appreciated.
Instead of handling it in WriteCSV, you could pre-process the data to flatten (denormalize) it and then pass it to your existing WriteCSV:
var flatten = l.SelectMany(po => po.PurchaseOrderItems.Select(pi => new {
po.WHID,
po.Supplier_ID,
po.POID,
pi.SKU,
pi.Product_ID,
pi.QtyOrdered,
}));
WriteCSV(flatten);
I am trying to display the 'names' of the dialects (from 'lu_dialect_t') of the Parents of a specific Child. I am doing multiple left joins with the LINQ query and now I am hoping to find a way on how to GROUP the query by the 'parent_id' and concatenate the 'name' (of dialects spoken by the parent) to one column and store it in a variable for my ViewModel.
This is my ViewModel:
public class ParentViewModel
{
public int parent_id { get; set; }
public string last_name { get; set; }
public string first_name { get; set; }
public string middle_name { get; set; }
public string ext_name { get; set; }
public Nullable<System.DateTime> birthdate { get; set; }
public string civil_status { get; set; }
public string email_address { get; set; }
public string cell_num { get; set; }
public string tel_num { get; set; }
public string fax_num { get; set; }
public string room_num_or_building { get; set; }
public string street { get; set; }
public string purok { get; set; }
public string subdivision { get; set; }
public Nullable<int> brgy_id { get; set; }
public string city_code { get; set; }
public string province_code { get; set; }
public string mother_tongue { get; set; }
public string educational_attainment { get; set; }
public string occupational_status { get; set; }
public string parent_type { get; set; }
public string deceased { get; set; }
public Nullable<System.DateTime> survey_date_conducted { get; set; }
public string person_who_conducted { get; set; }
public int child_id { get; set; }
public string parent_dialects { get; set; }
}
This is my Controller:
public ActionResult Parents(int id)
{ var query = (from p in db.parent_t
join cp in db.tn_child_parent_t on p.parent_id equals cp.parent_id into tcpGroup
from x in tcpGroup.DefaultIfEmpty()
join c in db.child_t on x.child_id equals c.child_id into cGroup
from y in cGroup.DefaultIfEmpty()
join pd in db.tn_parent_dialect_t on p.parent_id equals pd.parent_id into tpdGroup
from a in tpdGroup.DefaultIfEmpty()
join d in db.lu_dialect_t on a.dialect_id equals d.dialect_id into dGroup
from b in dGroup.DefaultIfEmpty()
where (y.child_id == id)
select new ViewModels.ParentViewModel
{
parent_id = p.parent_id,
last_name = p.last_name,
first_name = p.first_name,
middle_name = p.middle_name,
ext_name = p.ext_name,
birthdate = p.birthdate,
civil_status = p.civil_status,
email_address = p.email_address,
cell_num = p.cell_num,
tel_num = p.tel_num,
fax_num = p.fax_num,
room_num_or_building = p.room_num_or_building,
street = p.street,
purok = p.purok,
subdivision = p.subdivision,
brgy_id = p.brgy_id,
city_code = p.city_code,
province_code = p.province_code,
mother_tongue = p.mother_tongue,
educational_attainment = p.educational_attainment,
occupational_status = p.occupational_status,
parent_type = p.parent_type,
deceased = p.deceased,
survey_date_conducted = p.survey_date_conducted,
person_who_conducted = p.person_who_conducted,
parent_dialects = b.name,
});
return View(query);
}
Right now, the query just displays shows my table like this:
My current progress
But what I want is like this:
The desired result
Please help, I have been trying to find a way to do this for hours. Thank you.
Here is something similar
static void Main(string[] args)
{
var items = Enumerable.Range(0, 10).Select(p => new { Name = "Name" + p%2, LasetName = "LN"+p%2, Dialect = "D"+p });
var data = from item in items
group item by item.Name into g
select new
{
Name = g.Key,
LastName = g.First().LasetName,
Dialect = string.Join(",", g.Select(d=>d.Dialect))
}
;
foreach (var item in data)
{
Console.WriteLine($"Name:{item.Name}, Dialect:{item.Dialect}");
}
Console.WriteLine("Done");
Console.ReadLine();
}
Post process the var query with your group by and youse first for all the single properties you need. If you are using EF you will need to do a ToList first to get the data to memory for the concatenation. Also if there is a lot of data pulling all the rows in memory is not the best.
I'm trying to learn how to use LINQTOExcel to query a CSV file. Following the tutorial on the site I adapted their example to work with my data (filename is passed to it via an OpenDialog component):
var csv = new ExcelQueryFactory(filename);
var test = from c in csv.Worksheet<TestData>()
select c;
foreach(var t in test)
{
Console.WriteLine(t.Contract_Id);
}
I've got a separate TestData class/model which looks like this:
class TestData
{
public string Transaction_Id { get; set; }
public string Value_Date { get; set; }
public string Transmit_Date { get; set; }
public string Transmit_Time { get; set; }
public string Contract_Id { get; set; }
public string Contract_Amount { get; set; }
public string Contract_Rage { get; set; }
public string TestAmount { get; set; }
public string Employer_Code { get; set; }
public string Test_Acceptor { get; set; }
public string Institution_Id { get; set; }
}
But when I loop through, all of the values for each item are 'null'. Am I missing a step somewhere?
Example CSV Data:
transaction_id,value_date,transmit_date,transmit_time,contract_no,contract_amount,instalment,test_amount,employer_code,test_acceptor,institution_id
35454521,20111230,20120102,2:23:12,1442,1714.56,1,285.76,0,643650,a
The CSV file needs a header row that matches the property names:
Transaction_Id,Value_Date,Transmit_Date,Transmit_Time,Contract_Id,Contract_Amount,Contract_RageTestAmount,Employer_Code,Test_Acceptor,Institution_Id
35454521,20111230,20120102,2:23:12,1442,1714.56,1,285.76,0,643650