Just getting my head around all this LINQ stuff and it seems I'm stuck at the first hurdle.
I have a datatable as such:
OrderNo LetterGroup Filepath
----------- ----------- --------------------------------------------------
0 0 Letters/SampleImage.jpg
0 0 Letters/UKPC7_0.jpg
0 0 Letters/UKPC8_0.jpg
What I need is to get all of the filepaths from the Filepath column into a String array. I thought LINQ would be perfect for this (am I right?), but can't seem to construct the correct query.
Can anyone provide some code samples that would point me in the right direction? I have searched around - but don't seem to be getting anywhere.
There are extension methods which make working with data sets much easier:
using System.Data.Linq;
var filePaths =
from row in dataTable.AsEnumerable()
select row.Field<string>("Filepath");
var filePathsArray = filePaths.ToArray();
You can also use the method syntax to put it in one statement:
var filePaths = dataTable
.AsEnumerable()
.Select(row => row.Field<string>("Filepath"))
.ToArray();
string[] filePaths = (from DataRow row in yourDataTable.Rows
select row["Filepath"].ToString()).ToArray();
If you want to use LINQ all the way, set up your database and create a context object. Then you should be able to do something like this:
var filepaths = from order in _context.Orders
select order.Filepath;
This is assuming your table for the row is named Orders, which I guess by your first column name of order. If you wanted to return a set of the order numbers as well for using later to know where the file path came from you could do something like so:
var results = from order in _context.Orders
select new
{
order.OrderNo,
order.Filepath
}
This would give you a new anonymous type that contained both those values as properties.
Related
I have a datatable i create after reading in a txt file, once i have that datatable, i need to remove rows based on 1 column and a list of values List returnClass(), but after some testing, i found that my LINQ is removing more than expected... so not sure what im doing wrong with the code below.
At first i thought everything was good, because i was working with a large number of records and the numbers were going down with every pass, but now that im working with a small file to debug, i find out that its removing more than it should..
Here is my LINQ query:
// REMOVES ALL RECORDS WITH A CLASS THAT IS NON-LABEL CLASS
var query = from r in d.AsEnumerable()
where !returnClass().Any(r.Field<string>("Column7").Contains)
select r;
DataTable output = query.CopyToDataTable<DataRow>();
int dtoutputCount = output.Rows.Count;
ToCSV(output, ftype, "filteredclass");
Here is my list: (shorten to make this a simple question)
private List<string> returnClass()
{
List<string> cl = new List<string>();
cl.Add("7");
cl.Add("72");
return cl;
}
My datatable has 100 rows, the column7 has number in it, type string, i need to find each row that has the exact numbers in my list, so if it finds a 7, i dont want it and if it find a 72 i dont want it. BUT if there is a 75, or 17 or 127 those need to stay. And the query above is removing those because it contains the number 7.
How can i remove based on exact matches?
I think the problem is that you are actually looking to see if any value in your returnClass() list contains the value found in column7. Inside your Any function you are using String.Contains, and I'm guessing you expect this is a List.Contains or something along those lines.
Try this instead (untested):
// REMOVES ALL RECORDS WITH A CLASS THAT IS NON-LABEL CLASS
var query = from r in d.AsEnumerable()
where !returnClass().Contains(r.Field<string>("Column7"))
select r;
DataTable output = query.CopyToDataTable<DataRow>();
int dtoutputCount = output.Rows.Count;
ToCSV(output, ftype, "filteredclass");
I am trying to sort some data from entity before passing them to another function. Both tableName and columnName are selected dynamically. This is what I'm doing:
string tableName = cboSelectTable.Text.ToString();
var comboBoxColumn = from a in Context.RULES where
a.ISCOMBOBOXCOLUMN == "Y" select a.COLUMN;
foreach (var colName in comboBoxColumn)
{
var getTableName = entityModel.GetType()
.GetProperty(tableName)
.GetValue(entityModel, null);
var getData = ((IQueryable<object>)getTableName)
.Where(colName + "!=null")
.Select(colName)
.Distinct()
.OrderBy('"'+ colName +'"');
dgvCboColumn(getData, colName);
}
But this is not sorting the data. I also tried some other methods too, but couldn't figure it out. How can I resolve this?
I do not think that is the way, .OrderBy(...) works. Try ordering by an attribute:
SomeList.OrderBy(l => l.SomeAttribute);
I suspect ordering by a string results in each element being ordered by the same attribute, thus not ordering at all. In addition, I am not sure, if your where-clause works like that.
There is another relevant SO question already answered. You might want to have a look at it: click me!
You can simply place the Select after the OrderBy:
var getData = ((IQueryable<object>)getTableName)
.Where(colName + "!=null")
.OrderBy(colName)
.Select(colName)
.Distinct();
This will allow you to reference the column name. (doesn't seem to work for some reason).
Alternatively, you can reference the current instance:
var getData = ((IQueryable<object>)getTableName)
.Where(colName + "!=null")
.Select(colName)
.Distinct()
.OrderBy("it");
I'm trying to create a concise LINQ query to split a CSV file and convert to a XML file from a array of columns I have gleaned of a XSD file.
Its all working good. Except I just can't get the Counter to reset back to Zero after each row. It should go 0,1,2,3,4 then 0,1,2,3,4 but its going 0,1,2,3,4 then 5,6,7,8,9.
I'm new to LINQ so hopefully this is simple for someone with a bit of experience, thanks!
string[] columns = {"COL1","COL2","COL3","COL4","COL5"};
int Counter = 0;
XElement cust = new XElement("Root",
from str in source.Skip(1)
let fields = str.Split(',')
select new XElement("Records",
from c in columns
select new XElement(c, fields[Counter++])
)
);
That is not the way to do this. It is extremely bad practice to have side-effecting functions (like an incrementor) inside a LINQ select clause, particularly because of things like parallelization. If you were doing this manually with a foreach, I might be tempted to just suggest use of a mod:
fields[(Counter++) % fields.Length]
But even that would still be a little weird.
This is a more acceptable way, which uses the Zip method to find column names by matching them up by index.
string[] columns = {"COL1","COL2","COL3","COL4","COL5"};
var rows = source.Skip(1)
.Select(c => columns.Zip(c.Split(','),
(column, value) => new
{
Column = column,
Value = value
});
var elements = rows.Select(c => new XElement("Records",
c.Select(x => new XElement(c.Column, c.Value))));
return new XElement("Root", elements);
That all said, it's important to note that this is not currently generalizable, and will fail when the columns contain quoted values with commas in them. You might want to look into third party libraries. I've had luck with CsvHelper myself.
I am going to ask a very basic question and probably a repeated one but I have a bit different situation.
I want to use "in" operator in Linq.
I have to get all the rows from table which has Id provided
by my array and returns the row if it has. How can I do it.
My array has
var aa="1091","1092","1093" and so on.
and my table uses these Ids as Primary keys
.I have to get all the rows whose Id is contained in the array and I do not want to use S.P.
You can use Enumerable.Contains,
var aa = new string[3] { "1091", "1092", "1093" };
var res = yourDataSource.Where(c => aa.Contains(c.ID));
IN statements are created by using Contains in your Where call. Assuming you use integers as IDs, you could write something like this:
var myArray=new[]{1091,1092,1094};
var myEntities=from entity in myTable
where myArray.Contains(entity.ID)
select entity;
I'm fairly new to LINQ (and SQL at that). When trying to query my SQL Database in C# "Supervisors" (which contains only one column "Names" made of nvarchar(50) variables, none of which are Null), supvName ends up being an empty list. If I don't cast it as a List, supvName is of typeSystem.Data.EnumerableRowCollection<string> if that helps.
public addNewEmp()
{
InitializeComponent();
using (TestDataSet db = new TestDataSet())
{
var supvName = (from n in db.Supervisors
select n.Names).ToList();
foreach (string n in supvName)
{
supv_cbox.Items.Add(n);
}
}
}
Even when using a Where statement, that one result doesn't show up, so I'm sure it's something simple in my code that I just can't seem to figure out. I've already tried using AsEnumerable() which didn't change anything.
EDIT: I'm doing this in VS 2010 WPF. Also when I Preview Data in TestDataSet.xsd, it does return the all the data in the Database.
Solution: The problem was when I used a DataSet. When I used a DataContext instead it worked perfectly fine. Thanks to your DataSet or DataContext question lazyberezovsky or I never would have tried that.
Using the following works:
var supvName = db.Supervisors.Select(m => m.Names);
supv_cbox.ItemsSource = supvName;
Thanks Surjah Singh too.
When you are enumerating over DataTable with Linq to DataSet, you should call AsEnumerable() on datatable and use Field<T> extension to get column value:
var supvName = (from r in db.Supervisors.AsEnumerable()
select r.Field<string>("Names")).ToList();
BTW query variable r will be of DataRow type.
Your code can be simplified to:
var names = db.Supervisors.AsEnumerable().Select(r => r.Field<string>("Names"));
supv_cbox.DataSource = names.ToList();
//Var supvName = Supervisors.Select(m=>m.Names);
var supvName = from s in Supervisors.Tables[0].AsEnumerable()
select s.Field<string>("Names");