How to select a field with linq on datarow - c#

I have this linq query :
string title = from DataRow r in (OleDB.DataItems.Tables[0]).Rows
select r.Title;
and I'd like to extract the field Title (from Database) on the row (rows will be 1, not more, so that's I put on a string and not in a string[].
How can I do it?
VStudio says that DataRow doesnt contain the definition of Title, but the field Title exist on the database.
I making confusion :)

As Frédéric Hamidi said, you don't need LINQ.
However, if you still want to do it that way (overkill) and you know that there is always a single table with a single row, do:
DataSet data = new DataSet();
var table = (from a in data.Tables.Cast<DataTable>() select a).Single();
var row = (from a in table.Rows.Cast<DataRow>() select a).Single();
String title = row.Field<String>("Title");
or
DataSet data = new DataSet();
var table = (from a in data.Tables.Cast<DataTable>() select a).SingleOrDefault();
var row = (from a in table.Rows.Cast<DataRow>() select a).SingleOrDefault();
String title = row.Field<String>("Title");
I used a DataSet because I don't know how your object is structured.

You don't need LINQ since you only want to fetch the Title field of the first row in the collection:
string title = OleDB.DataItems.Tables[0].Rows[0]["Title"];

try
string title = (from DataRow r in (OleDB.DataItems.Tables[0]).Rows
select r.Title).First();
Linq returns an enumerable collection as it doesn't know there will be only one item. Calling the First method will return the first item from the query.
Edit: Hang on, I have blatantly missed the problem you originally mentioned (but you'll still need the above)!
A data row contains fields, not properties as such. What you'll need to do is
select r.Field<string>("Title")
So your entire query will be
string title = (from DataRow r in (OleDB.DataItems.Tables[0]).Rows
select r.Field<string>("Title")).First();

It's better to use FirstOrDefault, in case there are no rows:
string title = (from DataRow r in (OleDB.DataItems.Tables[0]).Rows
select r.Title).FirstOrDefault();

Usually, if you need to perform such an action, you would cast the DataRow object to your strongly typed object corresponding with the table in your database.
I assume there is a class "Book" which contains the field "Title":
Book selectedBook = (Book) from DataRow r in (OleDB.DataItems.Tables[0]).Rows[0]
string sTitle = selectedBook.Title;
Hope this helps.

Related

Multiple string values to compare with one. something like attributetocheck.Equals(att1,att2,att3)

I have multiple attributes say att1,att2,att3 which can be separated by any of the separator.
I want to have an "OR" condition in the below query to check if the row value in COLUMN1 is equal or not.
Since .Equals can only have a string ,Can any one suggest any other way of doing it.
string result = string.Join(",", attributes);
List<string> query = (from DataRow dr in response.Output.Tables[0].Rows
where dr["COLUMN1"].ToString().Equals(result)
select dr["COLUMN2"].ToString()).ToList<string>();
Instead of joining attributes to an string, use it's Contains method
List<string> query = (from DataRow dr in response.Output.Tables[0].Rows
where attributes.Contains(dr["COLUMN1"].ToString())
select dr["COLUMN2"].ToString()).ToList<string>()

LIKE query on DataTable using LINQ

Ive just started learning Linq. Ive just created a sample test like this.
Dim dt As New DataTable
Dim dc As New DataColumn
dc.ColumnName = "Test"
dt.Columns.Add(dc)
dt.Rows.Add("Test")
dt.Rows.Add("One test")
dt.Rows.Add("Second test")
Dim results = From myRow In dt.AsEnumerable
Where myRow("Test") = "Test"
Select myRow
For Each Row In results
Console.WriteLine(Row.Item(0).ToString())
Next
This returns the first row in the iteration.
But what if i want to use a LIKE operator using %? I cant get it to work.
Ive tried
Where myRow("Test") LIKE "Test%"
Sounds to me like you want to use StartsWith i.e.
Dim results = From myRow In dt.AsEnumerable
Where myRow("Test").StartsWith("Test")
Select myRow
Contains will match anywhere in the string where as StartsWith will only match if it's at the beginning of the string (same logic as Test%).
You migh be looking for contains.
Take a look at this:
var query = from mem in context.Member
where mem.LastName.Contains("xxx")
orderby mem.LastName, mem.FirstName
select new
{
FirstName = mem.FirstName,
LastName = mem.LastName,
};
You can also use .StartsWith() or .EndsWith().
You can use the contains method:
Dim results = From myRow In dt.AsEnumerable
Where myRow("Test").Contains("Test")
Select myRow

Return columns from identified in List<string> in linq select clause at runtime

I have looked at Dynamic linq but I am obviously missing something.
I am attempting to import files from one system to another. I have a DataTable loaded from an Excel sheet containing file information. (ExcelDataTable). I also have a HastSet of files that the user would like to import. (FilesToImport). The user selects which information he would like to import from the speadsheet, and those columns are dynamic and selected at runtime. (List VariablesToUpdate). I am joining on my ID in the query but I am not sure how to return the required columns from the datatable.
DataTable dt = new DataTable();
var query =
from excelRow in this.ExcelDataTable.AsEnumerable()
join file in this.FilesToImport.AsEnumerable()
on excelRow.Field<Guid>("ceGuid") equals file.SourceFileIdentifier
select dt.LoadDataRow(new object[]
<COMPLETELY LOST HERE>
, false);
query.CopyToDataTable();
I can work it out if I know what I would like to return using something like;
select new { ImportSourceFilePath = excelRow.Field<string>(filePathColumn)};
but like I said my columns will vary and I won't know until runtime what they are.
Any ideas?
You can use ExpandoObject for your implementation.
Here is a little tutorial for ExpandoObject
What I ended up doing;
var foundExcelRows =
from excelRow in this.ExcelDataTable.AsEnumerable()
join file in this.FilesToImport.AsEnumerable()
on excelRow.Field<Guid>("ceGuid") equals file.SourceFileIdentifier
select excelRow;
for (int i = 0; i < foundExcelRows.Count(); i++)
{
DataRow row = foundExcelRows.ElementAt(i);
// work with this row since I know the columns I expect
}

C# DataTable Linq select distinct values where column equals 'x'

I have a Datatable (Groups) designed like so
ColumnA|ColumnB
X|Apple
Y|Purple
X|Apple
X|Mango
I basically want to select from columna where it's X and get the disinct from ColumnB
This is what I have
var names = (from DataRow dr in Groups.Rows
orderby (string)dr["ColumnB"]
select (string)dr["ColumnB"]).Distinct();
This will give me distinct but it gives me Purple, and i dont want purple.
Thanks!
var names = (from DataRow dr in Groups.Rows
where dr["ColumnA"] == "X"
orderby (string)dr["ColumnB"]
select (string)dr["ColumnB"]).Distinct();
DataTable dt2 = dt1.Select("ColumnA = 'X'").CopyToDataTable().DefaultView.ToTable(true, "ColumnB");
So here we are selecting only the rows of data that you want, only rows where columnA is X. Then we choose only to see columnB, but with unique values only. Doing it in this order, you'll receive another datatable to play with. It'll only contain 1 column, columnB, and it'll only have unique/distinct values.
Enjoy.
If your return has more than one value and you want to Distinct the whole set by just one of the values you should use a custom IEqualityComparer.
var names = (from DataRow dr in Groups.Rows
where (string)dr["ColumnA"] == "X"
orderby (string)dr["ColumnB"]
select new {
ColumnA = (string)dr["ColumnA"],
ColumnB = (string)dr["ColumnB"]
}).Distinct(new MyCustomEqualityComparer());
edit: to include where clause
edit2: changed to custom IEqualityComparer

Error when Copying Query from linq to Datatable

I just started working on a project that requires Linq to Sql, and I have been able to make queries and retrieve data. But right now I need to fill a DataTable with the data I am retrieving.
My first code was the following:
MyDatabase db = new MyDatabase();
var query = from cust in db.Customers
where cust.CustomerName != "Dante"
orderby cust.CustomerName
select new { Name = cust.CustomerName };
So, since I needed to copy the content of my query to a Datatable I tried this:
IEnumerable<DataRow> query =
from order in orders.AsEnumerable()
where order.Field<DateTime>("OrderDate") > new DateTime(2001, 8, 1)
select order;
// Create a table from the query.
DataTable boundTable = query.CopyToDataTable<DataRow>();
Then, my code looks like this:
IEnumerable<DataRow> myQuery = from cust in db.Customers.AsEnumerable()
where cust.Name != "Dante"
orderby cust.Name
select new { Name = cust.Name };
DataTable myDataTable = myQuery.CopyToDataTable<DataRow>();
But with this code the compiler raises and error:
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<AnonymousType#1>' to 'System.Collections.Generic.IEnumerable<System.Data.DataRow>
The error is raised at the select word.
So, What am I doing wrong?? What can I do in order to avoid this conversion issue?
Hope someone can help me, thanks in advance.
There is a way to create a DataTable from a result other than IEnumerable<DataRow>, but it is rather involved. Implement CopyToDataTable Where the Generic Type T Is Not a DataRow.
For your case, though, I would recommend doing it the following way. Go back to your original query:
MyDatabase db = new MyDatabase();
var query = from cust in db.Customers
where cust.CustomerName != "Dante"
orderby cust.CustomerName
select new { Name = cust.CustomerName };
Then define your single field DataTable because when you eventually create a DataRow, it needs a schema to work from:
DataTable myDataTable = new DataTable();
myDataTable.Columns.Add(
new DataColumn()
{
DataType = System.Type.GetType("System.String"),
ColumnName = "Name"
}
);
And finally, go through the results of your query and manually add the DataRows to your DataTable.
foreach (var element in query)
{
var row = myDataTable.NewRow();
row["Name"] = element.Name;
myDataTable.Rows.Add(row);
}
The problem is exactly as the error states; your "select" clause is creating instances of an anonymous type with one member, "Name". This anonymous type is not and cannot be a DataRow, so the implicit conversion between what the query produces and the variable you want to set it into fails.
Instead, you should take this query, and for each element of the anonymous type that it returns, add the value as a new DataRow of the DataTable. You cannot just create a new DataRow from scratch; the DataRow class requires a context, namely the parent DataTable, to define the columns the DataRow should have.
This will do i guess
var myQuery = from cust in db.Customers.AsEnumerable()
where cust.Name != "Dante"
orderby cust.Name
select new { Name = cust.Name };
or try this
string[] myQuery = db.Customers.Rows
.Cast<DataRow>()
.Where(r=>r.Name!="Dante")
.Orderby(r=>r.Name)
.Select(r=>r.Field<string>("Name"))
.ToArray()

Categories

Resources