Linq: DataTable to List. Cast issue - c#

I'm getting the Specified cast is not valid. and I can't find why. Here's my code.
Object Layer.
public class Supervisor
{
public long ID { get; set; }
public string stringField1 { get; set; }
public string stringField2 { get; set; }
public string stringField3 { get; set; }
public int intField1{ get; set; }
public int intField2 { get; set; }
}
C# Method.
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public static string GetPend(string value1FromjqGrid, string value2FromjqGrid)
{
string query = "GetPend";
string supervisor = "";
Supervision _query = new Supervision();
DataTable dt = _query.GetSupervisorQuery(value1FromjqGrid, value2FromjqGrid, supervisor, query );
List<Supervisor> lines = (from dt1 in dt.AsEnumerable()
select new Supervisor()
{
ID = dt1.Field<long>("ID"),
stringField1 = dt1.Field<string>("Linea"),
intField1 = dt1.Field<int>("Tiempo"),
intField2 = dt1.Field<int>("TIPOACTIVIDAD_ID"),
stringField2 = dt1.Field<string>("ACT_ID"),
stringField3 = dt1.Field<string>("OBS")
}).ToList();
var grid = new
{
page = 1,
records = lines.Count(),
total = lines.Count(),
rows = from item in lines
select new
{
id = item.ID,
cell = new string[]{
item.stringField1,
item.intField1.ToString(),
item.intField2.ToString(),
item.stringField2,
item.stringField3
}
}
};
return JsonConvert.SerializeObject(grid);
}
That's it more or less. When the LinQ iteration starts it crashes. The DataTable is filled correctly as I've checked, and dt1 contains the fields correctly. I see the "" for the string columns and the numbers for the int's (I've done the SQL Stored Procedure myself so I did the checking there too.) With this I'm also assuring that the 2 parameters from the jqGrid are OK, but still I placed some alerts just right before the calling and yes, they are fine.
I've pasted the code it seems to be relevant since the error comes when the codes trying to parse the information from the DataTable to the List, if you'd need to check the javascript involved here just let me know but I don't think that's needed.
Clearly I'm not seeing something so hopefully you can guide me in the right direction. Thanks.
PS. I've tried to check it out at LINQPad4 but I can't give it a try since I don't know how to represent the original DataTable variable there.
Update.
This is what VS gives to me when I expand the error.:
at System.Data.DataRowExtensions.UnboxT`1.ValueField(Object value)
at System.Data.DataRowExtensions.Field[T](DataRow row, String columnName)
at WEB.Supervisor.<GetPend>b__b(DataRow dt1) in E:\Dev\VS\WEB\Supervisor.aspx.cs:line 110
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at WEB.Supervisor.GetPend(String value1FromjqGrid, String value2FromjqGrid) in E:\Dev\VS\WEB\Supervisor.aspx.cs:line 109
Lines 109 and 110 are these
List<Supervisor> lines = (from dt1 in dt.AsEnumerable()
select new Supervisor()
It crashes at the beggining of the convert process.
UPDATE 2
According to comments I did as follows.
Took the SELECT and turned into a SELECT INTO for generating a trash table. Then checked its design and for my honest surprise, the field CAST(ACT_ID AS NVARCHAR(50)) was still decimal and not nvarchar as I expected.
So, seems like I have to handle this in LinQ as a decimal, or could I do something else? I've tried working with decimals in the past and didn't succed.

It should be type mismatch between column type in the database and the type of data used in List<Supervisor> lines = (from dt1 in dt.AsEnumerable() select new Supervisor() {...}).ToList();.
After some conversation in comments we could see that the type of "ACT_ID" is decimal in the database. So to fix the exception problem one can do something like the following:
List<Supervisor> lines = (from dt1 in dt.AsEnumerable()
select new Supervisor {
ID = dt1.Field<long>("ID"),
stringField1 = dt1.Field<string>("Linea"),
intField1 = dt1.Field<int>("Tiempo"),
intField2 = dt1.Field<int>("TIPOACTIVIDAD_ID"),
stringField2 = dt1.Field<decimal>("ACT_ID").ToString(),
stringField3 = dt1.Field<string>("OBS")
}).ToList();

Related

How do I read Child Nodes in Xml file using MVC

## XML FİLE ##
<Title month="1" year="2016">
<film day="1">
<morning>
Fight Club
</morning>
<night>
Inceptıon
</night>
</film>
<film day="2">
<morning>
xyzasda
</morning>
<night>
czxsadasas
</night>
</film>
</Title>
MY CLASS
public class FilmController : Controller
{
public ActionResult DisplayXML()
{
var data = new List<Films>();
data = ReturnData();
return View(data);
}
private List<Films> ReturnData(){
string xmldata = "myxmldata.xml";
DataSet ds = new DataSet();
ds.ReadXml(xmldata);
var filmlist= new List<Films>();
filmlist= (from rows in ds.Tables[0].AsEnumerable()
select new Films
{
month= Convert.ToInt32(rows[0].ToString()),
year= rows[1].ToString(),
film= rows[2].ToString(),
morning= rows[3].ToString(),
night= rows[4].ToString(),
}).ToList();
return filmlist;
}
}
Model
public int month{ get; set; }
public string year{ get; set; }
public string day { get; set; }
public string morning { get; set; }
public string night{ get; set; }
How to read child node? I want to create a table. I will create a table using this data. I want to keep it on a list.
I edited..
Error: Additional information: Cannot find column 3.
where is the error? I want to read the xml file.
You can parse your XML with the following:
var xml = XDocument.Load(xmlFile);
var films = xml.Descendants("film").Select(d => new Films()
{
month = Convert.ToInt32(d.Parent.Attribute("month").Value),
year = d.Parent.Attribute("year").Value,
day = d.Attribute("day").Value,
morning = d.Element("morning").Value,
night = d.Element("night").Value
});
See it in action HERE.
You can retrieve Films collection using Linq-To-XML easily like this:
XDocument xdoc = XDocument.Load(xmldata);
List<Films> result = xdoc.Descendants("film")
.Select(x =>
{
var film = x;
var title = x.Parent;
return new Film
{
month = (int)title.Attribute("month"),
year = (string)title.Attribute("year"),
day = (string)film.Attribute("day"),
morning = (string)film.Element("morning"),
night = (string)film.Element("night")
};
}
).ToList();
This will return two films, and each will have month & year based on Title node.
Code Explanation:
First we are finding all the film nodes, then projecting it using Select. In the select clause we can save variable for each film (you can think of film inside select method like alias in foreach loop). Also, we are storing the parent Title node in title variable. After this all we need to do is read the elements & attributes.
If understanding Method syntax is difficult, then here is the equivalent query syntax:
List<Films> result2 = (from x in xdoc.Descendants("film")
let film = x
let title = x.Parent
select new Film
{
month = (int)title.Attribute("month"),
year = (string)title.Attribute("year"),
day = (string)film.Attribute("day"),
morning = (string)film.Element("morning"),
night = (string)film.Element("night")
}).ToList();
Working Fiddle
When i read your xml in a dataset i get 2 tables
Table 1 "Title" with one row and 3 columns
Table 2 "film" with two rows and 4 columns
you read on Tables[0] (3 columns) - and you try to read 4th column of 3..
you need to change your loop - since you need to load Data from two tables.

Updating entire node with mutating cypher in Neo4jclient

I need to update all the properties of a given node, using mutating cypher. I want to move away from Node and NodeReference because I understand they are deprecated, so can't use IGraphClient.Update. I'm very new to mutating cypher. I'm writing in C#, using Neo4jclient as the interface to Neo4j.
I did the following code which updates the "Name" property of a "resunit" where property "UniqueId" equals 2. This works fine. However,
* my resunit object has many properties
* I don't know which properties have changed
* I'm trying to write code that will work with different types of objects (with different properties)
It was possible with IGraphClient.Update to pass in an entire object and it would take care of creating cypher that sets all properies.
Can I somehow pass in my object with mutating cypher as well?
The only alternative I can see is to reflect over the object to find all properties and generate .Set for each, which I'd like to avoid. Please tell me if I'm on the wrong track here.
string newName = "A welcoming home";
var query2 = agencyDataAccessor
.GetAgencyByKey(requestingUser.AgencyKey)
.Match("(agency)-[:HAS_RESUNIT_NODE]->(categoryResUnitNode)-[:THE_UNIT_NODE]->(resunit)")
.Where("resunit.UniqueId = {uniqueId}")
.WithParams(new { uniqueId = 2 })
.With("resunit")
.Set("resunit.Name = {residentialUnitName}")
.WithParams(new { residentialUnitName = newName });
query2.ExecuteWithoutResults();
It is indeed possible to pass an entire object! Below I have an object called Thing defined as such:
public class Thing
{
public int Id { get; set; }
public string Value { get; set; }
public DateTimeOffset Date { get; set; }
public int AnInt { get; set; }
}
Then the following code creates a new Thing and inserts it into the DB, then get's it back and updates it just by using one Set command:
Thing thing = new Thing{AnInt = 12, Date = new DateTimeOffset(DateTime.Now), Value = "Foo", Id = 1};
gc.Cypher
.Create("(n:Test {thingParam})")
.WithParam("thingParam", thing)
.ExecuteWithoutResults();
var thingRes = gc.Cypher.Match("(n:Test)").Where((Thing n) => n.Id == 1).Return(n => n.As<Thing>()).Results.Single();
Console.WriteLine("Found: {0},{1},{2},{3}", thingRes.Id, thingRes.Value, thingRes.AnInt, thingRes.Date);
thingRes.AnInt += 100;
thingRes.Value = "Bar";
thingRes.Date = thingRes.Date.AddMonths(1);
gc.Cypher
.Match("(n:Test)")
.Where((Thing n) => n.Id == 1)
.Set("n = {thingParam}")
.WithParam("thingParam", thingRes)
.ExecuteWithoutResults();
var thingRes2 = gc.Cypher.Match("(n:Test)").Where((Thing n) => n.Id == 1).Return(n => n.As<Thing>()).Results.Single();
Console.WriteLine("Found: {0},{1},{2},{3}", thingRes2.Id, thingRes2.Value, thingRes2.AnInt, thingRes2.Date);
Which gives:
Found: 1,Foo,12,2014-03-27 15:37:49 +00:00
Found: 1,Bar,112,2014-04-27 15:37:49 +00:00
All properties nicely updated!

List<object> Self-Filter

I have a list like
List<VoieData> listVoieData = new List<VoieData>();
and in VoieData Class I have :
public class VoieData
{
public int Depart { set; get; }
public int Arrive { set; get; }
public int DistanceDepart { set; get; }
public int DistanceArrive { set; get; }
}
Since I have a massive values I want to only consider all my Depart number , I would like to filter the listVoieData by finding the Arrive only have the same value as the
Depart
for example I have
listVoieData.Select(p=>p.Depart).ToList()= List<int>{1,2,3};
listVoieData.Select(p=>p.Arrive).ToList()= List<int>{1,2,3,4,5};
I need to throw away the entire VoieData which contain {4,5} as Arrive
right now my soulution is like this , but it' s not correct ;
List<VoieData> listVoieDataFilter = listVoieData .Join(listVoieData , o1 => o1.Arrive, o2 => o2.Depart, (o1, o2) => o1).ToList();
Sorry for the confusing question ;
I want to remove Arrive which is different from all the Depart in the list list , and return the new
List
it 's not only in one VoieData;
Arrive!=Depart
Thanks
I think you want to remove all objects where Arrive is not in any of the Depart from any object. In that case, first get all Depart and then filter by Arrive:
HashSet<int> allDepart = new HashSet<int>(listVoieData.Select(x => x.Depart));
var result = listVoieData.Where(v => !allDepart.Contains(v.Arrive))
We use a HashSet<int> for efficiency.
Use LINQ Where:
var records = listVoieData.Where(x => x.Arrive == x.Depart);
This will return results where both Arrive and Depart are the same.
That would be a typical case to use linq.
something like:
var res = from data in listVoieData
where data.Depart == data.Arrive
select data;
and then optionally just use res.ToArray() to run the query and get the array.
Since you've stated that you want:
I want to remove Arrive which is different from all the Depart
This can be re-phrased as, "The set of all arrivals except those in the set of departures", which translates very nicely into the following LINQ query:
var arrivalsWithNoDepartures = listVoieData.Select(p=>p.Arrive)
.Except(listVoieData.Select(p=>p.Depart));

Reading from .txt file, then exporting data to DataGridView

I know this is a laughable question, but God, I've spent my entire last day banging my head with it and it just won't work! The goddamn teacher didn't even mention anything about importing any data into DataGridView!
I have a C# Windows Forms homework assignment: I have to read data from a .txt (users) file and paste it into a DataGridView table in C# Microsoft Visual Studio 2012. The data in the users.txt file is something like that with TAB delimiters:
-------------------------------------------------
ID Name Surname Telephone VIP Age Balance
-------------------------------------------------
0001 John Killer 1-500-300 0 13 2272
0002 Name Surname 1-500-200 0 27 225
0003 Martin King 1-500-400 1 41 1070
Ignore the label names (ID, Name, Surname...), I wrote them only for clarity, the real file has only the raw user data in it.
Now, I have previously created a class Users, which has these fields:
ID
Name
Surname
Telephone
VIP
Bought items
Price
and then created a DataGridView (usersDataGridView) and imported the fields from class Users in it.
OK, algorithmically this is somewhat easy task, ain't it?
My idea was doing the following: reading the file content with a StreamReader, saving each line to a string, then splitting the string into parts using \t as a delimiter with String.Split.
However, once I got those lines split... well, I basically have no idea how to import them into the DataGridView (I "know" it should be as a DataSource but... the Visual Studio 2012's UI seems way too "complicated" for me to let me figure out how I can point a string or whatever goddamn data type it is as a DataSource).
My pitiful attempts had led me to the following:
Attempt 1:
public void Test_1()
{
string filePath = string.Format("{0}/databases/{1}", AppDomain.CurrentDomain.BaseDirectory, "user_db.txt");
string[] textData = System.IO.File.ReadAllLines(filePath);
string[] headers = textData[0].Split('\t');
DataTable dataTable1 = new DataTable();
foreach (string header in headers)
dataTable1.Columns.Add(header, typeof(string), null);
for (int i = 1; i < textData.Length; i++)
dataTable1.Rows.Add(textData[i].Split('\t'));
//Set the DataSource of DataGridView to the DataTable
promotionsDataGridView.DataSource = dataTable1;
}
Attempt 2:
public void ReadFromFile()
{
string delimeter = "\t";
string tableName = "BooksTable";
string fileName = string.Format("{0}/databases/{1}", AppDomain.CurrentDomain.BaseDirectory, "bigtest.sql");
DataSet dataset = new DataSet();
StreamReader sr = new StreamReader(fileName);
dataset.Tables.Add(tableName);
dataset.Tables[tableName].Columns.Add("InventoryID");
dataset.Tables[tableName].Columns.Add("Brand");
dataset.Tables[tableName].Columns.Add("Category");
dataset.Tables[tableName].Columns.Add("Description");
dataset.Tables[tableName].Columns.Add("Promotions");
dataset.Tables[tableName].Columns.Add("Quantity");
dataset.Tables[tableName].Columns.Add("Price");
string allData = sr.ReadToEnd();
string[] rows = allData.Split("\r".ToCharArray());
foreach (string r in rows)
{
string[] items = r.Split(delimeter.ToCharArray());
dataset.Tables[tableName].Rows.Add(items);
}
this.productsDataGridView.DataSource = dataset.Tables[0].DefaultView;
}
However I keep getting some bullshit error like
Input array size is bigger than the whatever
Since I have literally no experience with DataGridView I guess I have some terrible mistakes at algorhitmic level, right?!
Please, anyone, help me! I have read, copied, pasted, compiled and debugged from like 20 different issues on similar topic and I am still at nowhere!
What's the proper way of reading data from a .txt file, then pasting it to a DataGridView?
Any help or answers are deeply appreciated!!
If you already have a User object defined you can add a static method to it that loads the data to a list of users and bind it to the grid view.
public class User {
public string Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string Telephone { get; set; }
public bool Vip { get; set; }
public int Age { get; set; }
public decimal Balance { get; set; }
public static List<User> LoadUserListFromFile(string path) {
var users = new List<User>();
foreach (var line in File.ReadAllLines(path)) {
var columns = line.Split('\t');
users.Add(new User {
Id = columns[0],
Name = columns[1],
Surname = columns[2],
Telephone = columns[3],
Vip = columns[4] == "1",
Age = Convert.ToInt32(columns[5]),
Balance = Convert.ToDecimal(columns[6])
});
}
return users;
}
}
Then you can simply load that into a data grid:
usersDataGridView.DataSource = User.LoadUserListFromFile("user_db.txt");

When filling a combobox with data from a datatable, is there a way to 'get to' the other 'members' of the datatable?

Okay, I don't think this question has been asked here - or at least the search didn't find it...
I have a combobox I'm filling like so:
DataTable companies = master.master_getCompanies(); // returns a DataTable
cboCompany.DataSource = companies;
cboCompany.DisplayMember = "CompanyName";
cboCompany.ValueMember = "SQLID";
This works fine
Later, after the user selects an item from the drop down, is there a way to get other columns from the previous datatable?
I am hoping to get somthing like this:
string foo = ((some_cast)cboCompany.SelectedItem).members["column_bar"];
I really have no idea if anything like this is possible - it just 'feels' like I should be able to do it.
I know I can keep the datatable in memory, and use the SQLID (ValueMember) that the combobox is giving me to re-lookup the other column - and I guess that's my fall-back solution if no one else has a better idea by morning :)
Thanks for the help guys (and gals!)
You can try this (I tried in VS2010):
var row = (DataRowView)cboCompany.SelectedItem;
var value = row["{column name}"];
HTH
internal class Company
{
public string CompanyName { get; set; }
public string SQLID { get; set; }
public string column_bar { get; set; }
}
...
List<Company> list = new List<Company>();
list.Add(new Company { CompanyName = "aaaaaa", SQLID = "ssssss", column_bar = "ddddddd" });
list.Add(new Company { CompanyName = "zzzzzzz", SQLID = "xxxxxx", column_bar = "ccccccccc" });
cboCompany.DataSource = list;
cboCompany.DataBind();
// ...
string foo = ((List<Company>)cboCompany.DataSource).ElementAt(cboCompany.SelectedIndex).column_bar;

Categories