Read hierarchical XML and flatten into a List of objects? - c#

I have an XML document which I would like to read, flatten, and return a List<> of an object I called PMRow. For each CodingRow in the XML there should be a corresponding List element and the "header" details of the Invoice should simply repeat. Many of the XML elements will be ignored in this transformation at both the Invoice and CodingRow level. I've started writing the code below and I can't conceptualize where to go from there:
Incomplete code:
public static List<PMRow> ParseToPMRows(FileInfo myFile)
{
var xDoc = XDocument.Load(myFile.FullName);
var query = from element in xDoc.Element("InvoiceDocument").Element("Invoice").Element("CodingRows").Elements("CodingRow")
select
}
Target Class:
public class PMRow
{
public string SupplierCode { get; set; }
public string InvoiceNumber { get; set; }
public DateTime InvoiceDate { get; set; }
public decimal GrossSum { get; set; }
public decimal NetSum { get; set; }
public decimal TaxSum { get; set; }
public decimal CR_GrossSum { get; set; }
public string AccountNumber { get; set; }
public string DimCode1 { get; set; }
}
XML Docuemnt:
<InvoiceDocument>
<Method>Post</Method>
<Invoice>
<GrossSum nil="False">700.000000</GrossSum>
<InvoiceDate nil="False">2018-09-26</InvoiceDate>
<InvoiceNumber nil="False">180928003802901</InvoiceNumber>
<NetSum nil="False">700.000000</NetSum>
<PaidSum nil="False">0.000000</PaidSum>
<PaymentBlock nil="False">false</PaymentBlock>
<PaymentDate nil="False">0001-01-01</PaymentDate>
<SupplierCode nil="False">AQUINC</SupplierCode>
<SupplierParentId nil="False"></SupplierParentId>
<TaxCode nil="False"></TaxCode>
<TaxPercent nil="False">0.000000</TaxPercent>
<TaxPercent2 nil="False">0.000000</TaxPercent2>
<TaxSum nil="False">0.000000</TaxSum>
<OrderNumber nil="False"></OrderNumber>
<OrderInCoding nil="False" />
<CodingRows>
<CodingRow>
<GrossSum nil="False">500.000000</GrossSum>
<InternalStatus nil="False">Loaded</InternalStatus>
<AccountCode nil="False">1990</AccountCode>
<AccountName nil="False">Gain on Non-Operating Asset</AccountName>
<DimCode1 nil="False">01</DimCode1>
<DimName1 nil="False">Operating/Unrestricted</DimName1>
<MaterialGroup nil="False"></MaterialGroup>
<FiscalYear nil="False"></FiscalYear>
<DimCode3 nil="False">06</DimCode3>
<DimName3 nil="False">Sports</DimName3>
<DimCode4 nil="False">06500</DimCode4>
<DimName4 nil="False">Personal Training</DimName4>
<DimCode5 nil="False">6</DimCode5>
<DimName5 nil="False">Minneapolis</DimName5>
<DimCode6 nil="False"></DimCode6>
<DimName6 nil="False"></DimName6>
</CodingRow>
<CodingRow>
<GrossSum nil="False">200.000000</GrossSum>
<InternalStatus nil="False">Loaded</InternalStatus>
<AccountCode nil="False">2390</AccountCode>
<AccountName nil="False">Gain on Non-Operating Asset</AccountName>
<DimCode1 nil="False">02</DimCode1>
<DimName1 nil="False">Operating/Unrestricted</DimName1>
<MaterialGroup nil="False"></MaterialGroup>
<FiscalYear nil="False"></FiscalYear>
<DimCode3 nil="False">06</DimCode3>
<DimName3 nil="False">Sports</DimName3>
<DimCode4 nil="False">06500</DimCode4>
<DimName4 nil="False">Personal Training</DimName4>
<DimCode5 nil="False">6</DimCode5>
<DimName5 nil="False">Minneapolis</DimName5>
<DimCode6 nil="False"></DimCode6>
<DimName6 nil="False"></DimName6>
</CodingRow>
</CodingRows>
<InvoiceRows />
</Invoice>
Conceptualized target (two objects of type PMRow in a List):
AQUINC, 180928003802901, 9/26/2018, 700, 700, 0, 500, 1990, 01
AQUINC, 180928003802901, 9/26/2018, 700, 700, 0, 200, 2390, 02

Is this what you are looking for?
XElement invoice = xDoc.Root.Element("Invoice");
List<PMRow> rows = invoice
.Element("CodingRows")
.Elements("CodingRow")
.Select(codingRow => new PMRow
{
SupplierCode = invoice.Element("SupplierCode").Value,
InvoiceNumber = invoice.Element("InvoiceNumber").Value,
InvoiceDate = DateTime.Parse(invoice.Element("InvoiceDate").Value),
GrossSum = decimal.Parse(invoice.Element("GrossSum").Value),
NetSum = decimal.Parse(invoice.Element("NetSum").Value),
TaxSum = decimal.Parse(invoice.Element("TaxSum").Value),
CR_GrossSum = decimal.Parse(codingRow.Element("GrossSum").Value),
AccountNumber = codingRow.Element("AccountCode").Value,
DimCode1 = codingRow.Element("DimCode1").Value,
})
.ToList();
Note: the above assumes that all elements will be present and valid. If this is not the case, you will need to add appropriate handling for that.
Fiddle: https://dotnetfiddle.net/DjKcDg

I generally find more convenient to first serialize XML into class object and then iterate over serialzed object.
You only need
XmlSerializer serializer = new XmlSerializer(typeof(Invoice));
TextReader reader = new StringReader(source);
Invoice resultObj = (Invoice)serializer.Deserialize(reader);
var pmRows = resultObj.CodingRows.CodingRow.Select(item => new PMRow
{
CR_GrossSum = Convert.ToDecimal(resultObj.GrossSum.Text),
InvoiceDate = Convert.ToDateTime(resultObj.InvoiceDate.Text),
InvoiceNumber = resultObj.InvoiceNumber.Text,
SupplierCode = resultObj.SupplierCode.Text,
NetSum = Convert.ToDecimal(resultObj.NetSum.Text),
GrossSum = Convert.ToDecimal(resultObj.GrossSum.Text),
TaxSum = Convert.ToDecimal(resultObj.TaxSum.Text),
AccountNumber = item.AccountCode.Text,
DimCode1 = item.DimCode1.Text
}).ToList();
you can check my solution from https://dotnetfiddle.net/jr11hB

Try code below. I assumed they are multiple Invoice in a file so I had to use SelectMany() to return a flat list
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication75
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
ParseToPMRows(FILENAME);
}
public static List<PMRow> ParseToPMRows(string myFile)
{
XDocument xDoc = XDocument.Load(myFile);
var tempResults = xDoc.Descendants("Invoice").Select(x => new {
supplierCode = (string)x.Element("SupplierCode"),
invoiceNumber = (string)x.Element("InvoiceNumber"),
invoiceDate = (DateTime)x.Element("InvoiceDate"),
grossSum = (decimal)x.Element("GrossSum"),
netSum = (decimal)x.Element("NetSum"),
taxSum = (decimal)x.Element("TaxSum"),
codingRows = x.Descendants("CodingRow").Select(y => new {
crGrossSum = (decimal)y.Element("GrossSum"),
accounNumber = (string)y.Element("AccountCode"),
dimCode1 = (string)y.Element("DimCode1")
}).ToList()
}).ToList();
List<PMRow> rows = tempResults.Select(x => x.codingRows.Select(y => new PMRow()
{
SupplierCode = x.supplierCode,
InvoiceNumber = x.invoiceNumber,
InvoiceDate = x.invoiceDate,
GrossSum = x.grossSum,
NetSum = x.netSum,
TaxSum = x.taxSum,
CR_GrossSum = y.crGrossSum,
AccountNumber = y.accounNumber,
DimCode1 = y.dimCode1
})).SelectMany(x => x).ToList();
return rows;
}
}
public class PMRow
{
public string SupplierCode { get; set; }
public string InvoiceNumber { get; set; }
public DateTime InvoiceDate { get; set; }
public decimal GrossSum { get; set; }
public decimal NetSum { get; set; }
public decimal TaxSum { get; set; }
public decimal CR_GrossSum { get; set; }
public string AccountNumber { get; set; }
public string DimCode1 { get; set; }
}
}
For one Invoice you can use following :
public static List<PMRow> ParseToPMRows(string myFile)
{
XDocument xDoc = XDocument.Load(myFile);
var tempResults = xDoc.Descendants("Invoice").Select(x => new {
supplierCode = (string)x.Element("SupplierCode"),
invoiceNumber = (string)x.Element("InvoiceNumber"),
invoiceDate = (DateTime)x.Element("InvoiceDate"),
grossSum = (decimal)x.Element("GrossSum"),
netSum = (decimal)x.Element("NetSum"),
taxSum = (decimal)x.Element("TaxSum"),
codingRows = x.Descendants("CodingRow").Select(y => new {
crGrossSum = (decimal)y.Element("GrossSum"),
accounNumber = (string)y.Element("AccountCode"),
dimCode1 = (string)y.Element("DimCode1")
}).ToList()
}).FirstOrDefault();
List<PMRow> rows = tempResults.codingRows.Select(x => new PMRow()
{
SupplierCode = tempResults.supplierCode,
InvoiceNumber = tempResults.invoiceNumber,
InvoiceDate = tempResults.invoiceDate,
GrossSum = tempResults.grossSum,
NetSum = tempResults.netSum,
TaxSum = tempResults.taxSum,
CR_GrossSum = x.crGrossSum,
AccountNumber = x.accounNumber,
DimCode1 = x.dimCode1
}).ToList();
return rows;
}

Related

Filter based on a string value in List<string> column in a table Entity Framework Core

I have a table with the following structure (code first approach using Entity Framework Core) in PostgreSQL
public class Product_Order
{
[Key]
public string product_number { get; set; }
public string customer_product_number { get; set; }
public List<string> product_statuses { get; set; }
public bool is_test { get; set; } = false;
public DateTime created_at { get; set; } = DateTime.UtcNow;
public DateTime updated_at { get; set; } = DateTime.UtcNow;
public string created_by { get; set; } = "system";
public string updated_by { get; set; } = "system";
}
Now, the product_statuses column usually contains of a list of statuses - ready, pickedup, scheduled, closed, cancelled.
I need to come up with a solution which returns me a list of product orders which DOES NOT CONTAIN orders which are closed or cancelled.
Here's the solution that I have at the moment which is not filtering as expected
_context.Product_Order.Where(t => t.is_test && !t.statuses.Contains("closed") && !t.statuses.Contains("cancelled")).ToList();
I think your code is ok for your data structure to find that information. I have created a dummy class and list to replicate your data and list. And I was able to find data by using you code. Sample Code given below what I have tested =>
void Test()
{
List<Product_Order> items = new List<Product_Order>();
var temp = new Product_Order() { product_number = "001", isTest = true };
temp.product_statuses = new List<string>();
temp.product_statuses.Add("good");
temp.product_statuses.Add("greate");
temp.product_statuses.Add("new");
items.Add(temp);
temp = new Product_Order() { product_number = "002", isTest = true };
temp.product_statuses = new List<string>();
temp.product_statuses.Add("good");
temp.product_statuses.Add("bad");
temp.product_statuses.Add("notnew");
items.Add(temp);
temp = new Product_Order() { product_number = "003", isTest = true };
temp.product_statuses = new List<string>();
temp.product_statuses.Add("n/a");
temp.product_statuses.Add("bad");
temp.product_statuses.Add("Closed");
items.Add(temp);
temp = new Product_Order() { product_number = "004", isTest = false };
temp.product_statuses = new List<string>();
temp.product_statuses.Add("n/a");
temp.product_statuses.Add("bad");
temp.product_statuses.Add("Cancelled");
items.Add(temp);
var finalOutput = items.Where(c => c.isTest == true && !c.product_statuses.Where(v => v.ToLower() == "closed").Any() && !c.product_statuses.Where(v => v.ToLower() == "cancelled").Any()).ToArray();
}
public class Product_Order
{
public string product_number { get; set; }
public bool isTest { get; set; }
public List<string> product_statuses { get; set; }
}
Finally , I think it is your data what not wright with you lambda expression. So, I modified for you a little bit.And that is
FINAL ANSWER:
var finalOutput = _context.Product_Order.Where(c => c.isTest == true && !c.product_statuses.Where(v => v.ToLower() == "closed").Any() && !c.product_statuses.Where(v => v.ToLower() == "cancelled").Any()).ToArray();
Please check my code and let me know.

Get selected column from iqueryable

How can I return fieldList from an IQueryable object?
// fieldList="Code,Name";
var result = from Activity in query
select new
{
Code = Activity.Code,
Name = Activity.Name,
StatusCode = Activity.ClaimStatus.Name
};
DTO
public class CustomDto
{
public string Code { get; set; }
public string Name { get; set; }
public string StatusCode { get; set; }
}
Convert To Dto
var result = items.AsQueryable().Select(x => new CustomDto()
{
Code = x.Code,
Name = x.Name,
StatusCode = x.ClaimStatus
}).ToList();

Get 1 record from 2 tables ASP.NET

I am still an ASP.NET amateur and I've been working on an application that needs to calculate the hours an employee has worked if no special events have come up e.g the employee has been sick, I have 2 tables in my database, 1 with the employees. and a second table which holds the events. the events table is filled through a calendar and holds info like dates and who made the event.
My situation:
When the user clicks on an employee's detail page. I want the corresponding record of the employee, and the events he made. So I am assuming that I am looking for a join with linq.
An employee can make more than 1 event, let's say an employee needs to work overtime 3 days this month. then on the detail page, it should select the employee from the employee table and the 3 events from the events table.
Update
Thanks to Vladimir's help, a whole lot of errors are gone and the query works. Though it does not completely work as expected yet. it currently returns 1 employee and 1 event. While the employee that I am testing with, should have 4 events returned.
This is my Context
namespace hrmTool.Models
{
public class MedewerkerMeldingContext : DbContext
{
public MedewerkerMeldingContext() : base("name=temphrmEntities") { }
public DbSet<medewerker> medewerker { get; set; }
public DbSet<medewerker_melding> medewerker_melding { get; set; }
}
}
My current viewModel
namespace hrmTool.Models
{
public class MedewerkerMeldingViewModel
{
//Medewerker tabel
public int ID { get; set; }
public string roepnaam { get; set; }
public string voorvoegsel { get; set; }
public string achternaam { get; set; }
public string tussenvoegsel { get; set; }
public string meisjesnaam { get; set; }
public Nullable<System.DateTime> datum_in_dienst { get; set; }
public Nullable<System.DateTime> datum_uit_dienst { get; set; }
public int aantal_km_woon_werk { get; set; }
public bool maandag { get; set; }
public Nullable<System.TimeSpan> ma_van { get; set; }
public Nullable<System.TimeSpan> ma_tot { get; set; }
public bool dinsdag { get; set; }
public Nullable<System.TimeSpan> di_van { get; set; }
public Nullable<System.TimeSpan> di_tot { get; set; }
public bool woensdag { get; set; }
public Nullable<System.TimeSpan> wo_van { get; set; }
public Nullable<System.TimeSpan> wo_tot { get; set; }
public bool donderdag { get; set; }
public Nullable<System.TimeSpan> do_van { get; set; }
public Nullable<System.TimeSpan> do_tot { get; set; }
public bool vrijdag { get; set; }
public Nullable<System.TimeSpan> vr_van { get; set; }
public Nullable<System.TimeSpan> vr_tot { get; set; }
public bool zaterdag { get; set; }
public Nullable<System.TimeSpan> za_van { get; set; }
public Nullable<System.TimeSpan> za_tot { get; set; }
public bool zondag { get; set; }
public Nullable<System.TimeSpan> zo_van { get; set; }
public Nullable<System.TimeSpan> zo_tot { get; set; }
//Medewerker_Melding combi tabel
public int medewerkerID { get; set; }
public int meldingID { get; set; }
public System.DateTime datum_van { get; set; }
public Nullable<System.DateTime> datum_tot { get; set; }
public int MM_ID { get; set; }
public virtual ICollection<medewerker_melding> medewerker_melding { get; set; }
public virtual medewerker medewerker { get; set; }
}
}
My current query
using (var context = new MedewerkerMeldingContext())
{
var medewerkers = context.medewerker;
var medewerker_meldings = context.medewerker_melding;
var testQuery = from m in medewerkers
join mm in medewerker_meldings on m.ID equals mm.medewerkerID
where m.ID == id
select new MedewerkerMeldingViewModel
{
ID = m.ID,
roepnaam = m.roepnaam,
voorvoegsel = m.voorvoegsel,
achternaam = m.achternaam,
tussenvoegsel = m.tussenvoegsel,
meisjesnaam = m.meisjesnaam,
datum_in_dienst = m.datum_in_dienst,
datum_uit_dienst = m.datum_uit_dienst,
aantal_km_woon_werk = m.aantal_km_woon_werk,
maandag = m.maandag,
ma_van = m.ma_van,
ma_tot = m.ma_tot,
dinsdag = m.dinsdag,
di_van = m.di_van,
di_tot = m.di_tot,
woensdag = m.woensdag,
wo_van = m.wo_van,
wo_tot = m.wo_tot,
donderdag = m.donderdag,
do_van = m.do_van,
do_tot = m.do_tot,
vrijdag = m.vrijdag,
vr_van = m.vr_van,
vr_tot = m.vr_tot,
zaterdag = m.zaterdag,
za_van = m.za_van,
za_tot = m.za_tot,
zondag = m.zondag,
zo_van = m.zo_van,
zo_tot = m.zo_tot,
medewerkerID = mm.medewerkerID,
meldingID = mm.meldingID,
datum_van = mm.datum_van,
datum_tot = mm.datum_tot,
MM_ID = mm.ID
};
var getQueryResult = testQuery.FirstOrDefault();
Debug.WriteLine("Debug testQuery" + testQuery);
Debug.WriteLine("Debug getQueryResult: "+ getQueryResult);
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
if (testQuery == null)
{
return HttpNotFound();
}
return View(getQueryResult);
}
Returns: 1 instance of employee and only 1 event
Expected return: 1 instance of employee, 4 events
In your context DbContext is missing - so Linq to Entity can not find corresponding implementation of the query. And also DbContext operates with the
DbSets - so try:
public class MedewerkerMeldingContext : DbContext
{
public MedewerkerMeldingContext () : base(ConnectionStringKey)
{
};
public DbSet<medewerker> medewerker { get; set; }
public DbSet<medewerker_melding> medewerker_melding { get; set; }
}
then
using (var context = new MedewerkerMeldingContext())
{
var medewerkers = context.medewerker;
var medewerker_meldings = context.medewerker_melding;
var testQuery = from m in medewerkers
join mm in medewerker_meldings on m.ID equals mm.medewerkerID
where m.ID == id
select new MedewerkerMeldingViewModel
{
ID = m.ID,
roepnaam = m.roepnaam,
voorvoegsel = m.voorvoegsel,
achternaam = m.achternaam,
tussenvoegsel = m.tussenvoegsel,
meisjesnaam = m.meisjesnaam,
datum_in_dienst = m.datum_in_dienst,
datum_uit_dienst = m.datum_uit_dienst,
aantal_km_woon_werk = m.aantal_km_woon_werk,
maandag = m.maandag,
ma_van = m.ma_van,
ma_tot = m.ma_tot,
dinsdag = m.dinsdag,
di_van = m.di_van,
di_tot = m.di_tot,
woensdag = m.woensdag,
wo_van = m.wo_van,
wo_tot = m.wo_tot,
donderdag = m.donderdag,
do_van = m.do_van,
do_tot = m.do_tot,
vrijdag = m.vrijdag,
vr_van = m.vr_van,
vr_tot = m.vr_tot,
zaterdag = m.zaterdag,
za_van = m.za_van,
za_tot = m.za_tot,
zondag = m.zondag,
zo_van = m.zo_van,
zo_tot = m.zo_tot,
medewerkerID = mm.medewerkerID,
meldingID = mm.meldingID,
datum_van = mm.datum_van,
datum_tot = mm.datum_tot,
MM_ID = mm.ID
};
Debug.WriteLine("Debug testQuery" + testQuery);
var getQueryResult = testQuery.ToList();
Debug.WriteLine("Debug getQueryResult: " + getQueryResult);
var resultDictionary = getQueryResult.GroupBy(x => x.ID).ToDictionary(y => y.Key, z => z.ToList());
Debug.WriteLine("resultDictionary: " + resultDictionary);
var firstItem = resultDictionary.Values.First();
Debug.WriteLine("FirstItem: " + firstItem);
var Entity = new newEntity
{
//ID = firstItem.ID,
ID = firstItem.Select(x => x.ID).First(),
roepnaam = firstItem.Select(x => x.roepnaam).First(),
voorvoegsel = firstItem.Select(x => x.voorvoegsel).First(),
achternaam = firstItem.Select(x => x.achternaam).First(),
tussenvoegsel = firstItem.Select(x => x.tussenvoegsel).First(),
meisjesnaam = firstItem.Select(x => x.meisjesnaam).First(),
datum_in_dienst = firstItem.Select(x => x.datum_in_dienst).First(),
datum_uit_dienst = firstItem.Select(x => x.datum_uit_dienst).First(),
aantal_km_woon_werk = firstItem.Select(x => x.aantal_km_woon_werk).First(),
maandag = firstItem.Select(x => x.maandag).First(),
ma_van = firstItem.Select(x => x.ma_van).First(),
ma_tot = firstItem.Select(x => x.ma_tot).First(),
dinsdag = firstItem.Select(x => x.dinsdag).First(),
di_van = firstItem.Select(x => x.di_van).First(),
di_tot = firstItem.Select(x => x.di_tot).First(),
woensdag = firstItem.Select(x => x.woensdag).First(),
wo_van = firstItem.Select(x => x.wo_van).First(),
wo_tot = firstItem.Select(x => x.wo_tot).First(),
donderdag = firstItem.Select(x => x.donderdag).First(),
do_van = firstItem.Select(x => x.do_van).First(),
do_tot = firstItem.Select(x => x.do_tot).First(),
vrijdag = firstItem.Select(x => x.vrijdag).First(),
vr_van = firstItem.Select(x => x.vr_van).First(),
vr_tot = firstItem.Select(x => x.vr_tot).First(),
zaterdag = firstItem.Select(x => x.zaterdag).First(),
za_van = firstItem.Select(x => x.za_van).First(),
za_tot = firstItem.Select(x => x.za_tot).First(),
zondag = firstItem.Select(x => x.zondag).First(),
zo_van = firstItem.Select(x => x.zo_van).First(),
zo_tot = firstItem.Select(x => x.zo_tot).First()
};
Debug.WriteLine("Entity: " + Entity);
var plainValues = resultDictionary.Values.SelectMany(x => x).ToList();
var resultSchedule = plainValues.Select(x => new medewerker_melding
{
medewerkerID = x.medewerkerID,
meldingID = x.meldingID,
datum_van = x.datum_van,
datum_tot = x.datum_tot,
ID = x.MM_ID
}).ToList();
Entity.medewerker_melding = resultSchedule;
}
You need to check whether MedewerkerMeldingContext dbC = new MedewerkerMeldingContext(); is implementing IEnumerable<T> else, you will not be able to preform the desired action on the table.
This kind of error (Could not find an implementation of the query
pattern) usually occurs when:
You are missing LINQ namespace usage (using System.Linq)
Typeyou are querying does not implement IEnumerable<T>
What i'd recommend, first check the namespace.
Second check for the IEnumerable<T> implementation.
Your query is good enough, you take the context and perform the linq, no issue here. It is 90% that you forgot the namespace since context is already implementing the IEnumerable<T> interface.

Use LINQ to join 2 objects for each of its properties

I have created 2 models to store the results of an sql query. Now I would like to join them for each of the week's... (week1 = Record_id, week2 = Record_id)
to get a new Object in which I would have all the data from the 1st model, as well as map data from the "Category" Model to it.
I created a new Model for it, but I am not sure how to write a linq query
First Model:
public class CustomData
{
public string full_name { get; set; }
public string location { get; set; }
public int week1 { get; set; }
public int week2 { get; set; }
public int week3 { get; set; }
}
Second Model:
public class Category
{
public int Record_ID { get; set; }
public int Color{ get; set; }
public string Name { get; set; }
}
New Model for end result:
public class WeekView
{
public string full_name { get; set; }
public string location { get; set; }
public Category week1 { get; set; }
public Category week2 { get; set; }
public Category week3 { get; set; }
}
This should work:
List<CustomData> list = new List<CustomData>();
list.Add(new CustomData() { full_name = "test", location = "test", week1 = 0, week2 = 1, week3 = 2 });
list.Add(new CustomData() { full_name = "test2", location = "test2", week1 = 0, week2 = 12, week3 = 22 });
List<Category> categories = new List<Category>();
categories.Add(new Category { Color = 0, Name = "testName", Record_ID = 0 });
categories.Add(new Category { Color = 1, Name = "testName1", Record_ID = 1 });
categories.Add(new Category { Color = 2, Name = "testName2", Record_ID = 2 });
categories.Add(new Category { Color = 3, Name = "testName3", Record_ID = 12 });
categories.Add(new Category { Color = 4, Name = "testName4", Record_ID = 22 });
List<WeekView> results = new List<WeekView>();
results.AddRange(list.Select(x=>
new WeekView() { full_name = x.full_name,
location = x.location,
week1 = categories.FirstOrDefault(c => c.Record_ID == x.week1),
week2 = categories.FirstOrDefault(c => c.Record_ID == x.week2),
week3 = categories.FirstOrDefault(c => c.Record_ID == x.week3)
}));
Try out the following:
var result = (from cd in CustomDatas
join ca1 in Categories on cd.week1 equals ca.Record_ID into ca1r
from ca1 in ca1r.DefaultIfEmpty()
join ca2 in Categories on cd.week2 equals ca.Record_ID into ca2r
from ca2 in ca2r.DefaultIfEmpty()
join ca3 in Categories on cd.week3 equals ca.Record_ID into ca3r
from ca3 in ca3r.DefaultIfEmpty()
select new {
full_name = cd.full_name,
location = cd.location,
week1 = ca1,
week2 = ca2,
week3 = ca3
}

Combine contents of two files using LINQ to CSV

This is probably a dumb question, but I'm wondering how I would fill a list with the following data for a CSV file.
Here's the code so far,
class Info
{
[CsvColumn(Name = "Lease Name", FieldIndex = 1)]
public string leaseName2 { get; set; }
[CsvColumn(Name = "Field Name", FieldIndex = 2)]
public string fieldName2 { get; set; }
[CsvColumn(Name = "Reservoir", FieldIndex = 3)]
public string reservoir2 { get; set; }
[CsvColumn(Name = "Operator", FieldIndex = 4)]
public string operator2 { get; set; }
[CsvColumn(Name = "County", FieldIndex = 5)]
public string county2 { get; set; }
[CsvColumn(Name = "State", FieldIndex = 6)]
public string state2 { get; set; }
[CsvColumn(Name = "Majo", FieldIndex = 7)]
public string majo2 { get; set; }
[CsvColumn(Name = "Resv Cat", FieldIndex = 8)]
public string resvCat2 { get; set; }
[CsvColumn(Name = "Discount Rate", FieldIndex = 9)]
public double disRate2 { get; set; }
There are more columns I just did not want to list them all because that would be redundant. If anyone could help that would be greatly appreciated.
#GertArnold is right, you can use Union(). I used Concat() in my example. Union returns distinct records, Concat doesn't.
using System;
using System.Collections.Generic;
using System.Linq;
using LINQtoCSV;
namespace LinqCsvSandbox
{
class SampleData
{
[CsvColumn(Name = "ID", FieldIndex = 1)]
public string ID { get; set; }
[CsvColumn(Name = "PersonName", FieldIndex = 2)]
public string Name { get; set; }
public override string ToString()
{
return string.Format("{0}: {1}", ID, Name);
}
}
class Program
{
static void Main(string[] args)
{
var inputFileDescription = new CsvFileDescription
{
SeparatorChar = ',',
FirstLineHasColumnNames = false,
FileCultureName = "en-us",
EnforceCsvColumnAttribute = true,
};
CsvContext cc = new CsvContext();
IEnumerable<SampleData> data1 = cc.Read<SampleData>("File1.csv", inputFileDescription);
IEnumerable<SampleData> data2 = cc.Read<SampleData>("File2.csv", inputFileDescription);
IEnumerable<SampleData> all = data1.Concat(data2);
// Uncomment to see the items printed
//foreach(var item in all)
// Console.WriteLine(item);
cc.Write(all, "All.csv");
}
}
}
In my example, File1.csv contains
1,Fred
2,Wilma
File2.csv contains
3,Tango
4,Cash
And the resulting All.csv contains
ID,PersonName
1,Fred
2,Wilma
3,Tango
4,Cash
For those unfamiliar, Linq to CSV is available as a package from NuGet.
Here are a couple of ways, the first is just using an object initializer, the second transfers a small list to the your CSV list:
List<Info> infoList = new List<Info>
{
new Info()
{
leaseName2 = "x"
}
};
List<string> stringList = new List<string> {"xy", "zz"};
infoList.AddRange(stringList.Select(stringVal => new Info()
{
leaseName2 = stringVal
}));

Categories

Resources