Linq : select value in a datatable column - c#

How do you use LINQ (C#) to select the value in a particular column for a particular row in a datatable. The equivalent SQL would be:
select NAME from TABLE where ID = 0

Thanks for your answers. I didn't understand what type of object "MyTable" was (in your answers) and the following code gave me the error shown below.
DataTable dt = ds.Tables[0];
var name = from r in dt
where r.ID == 0
select r.Name;
Could not find an implementation of the query pattern for source type
'System.Data.DataTable'. 'Where' not found
So I continued my googling and found something that does work:
var rowColl = ds.Tables[0].AsEnumerable();
string name = (from r in rowColl
where r.Field<int>("ID") == 0
select r.Field<string>("NAME")).First<string>();
What do you think?

var name = from r in MyTable
where r.ID == 0
select r.Name;
If the row is unique then you could even just do:
var row = DataContext.MyTable.SingleOrDefault(r => r.ID == 0);
var name = row != null ? row.Name : String.Empty;

I notice others have given the non-lambda syntax so just to have this complete I'll put in the lambda syntax equivalent:
Non-lambda (as per James's post):
var name = from i in DataContext.MyTable
where i.ID == 0
select i.Name
Equivalent lambda syntax:
var name = DataContext.MyTable.Where(i => i.ID == 0)
.Select(i => new { Name = i.Name });
There's not really much practical difference, just personal opinion on which you prefer.

If the return value is string and you need to search by Id you can use:
string name = datatable.AsEnumerable().Where(row => Convert.ToInt32(row["Id"]) == Id).Select(row => row.Field<string>("name")).ToString();
or using generic variable:
var name = datatable.AsEnumerable().Where(row => Convert.ToInt32(row["Id"]) == Id).Select(row => row.Field<string>("name"));

var name = from DataRow dr in tblClassCode.Rows where (long)dr["ID"] == Convert.ToInt32(i) select (int)dr["Name"]).FirstOrDefault().ToString()

var x = from row in table
where row.ID == 0
select row
Supposing you have a DataTable that knows about the rows, other wise you'll need to use the row index:
where row[rowNumber] == 0
In this instance you'd also want to use the select to place the row data into an anonymous class or a preprepared class (if you want to pass it to another method)

Use linq and set the data table as Enumerable and select the fields from the data table field that matches what you are looking for.
Example
I want to get the currency Id and currency Name from the currency table where currency is local currency, and assign the currency id and name to a text boxes on the form:
DataTable dt = curData.loadCurrency();
var curId = from c in dt.AsEnumerable()
where c.Field<bool>("LocalCurrency") == true
select c.Field<int>("CURID");
foreach (int cid in curId)
{
txtCURID.Text = cid.ToString();
}
var curName = from c in dt.AsEnumerable()
where c.Field<bool>("LocalCurrency") == true
select c.Field<string>("CurName");
foreach (string cName in curName)
{
txtCurrency.Text = cName.ToString();
}

Related

Grouping on virtual (predefined) column in linq

I am trying to write a linq query for one of my dashboard which retrieves data based on some conditions. I want to display records count based on the different status available in my table.
Following is the SQL query in which I am trying to convert into Linq.
select count(id) cnt, 'Available' label from table where date = sysdate
Above query is returning below result in DB IDE. This is the result I want with linq
cnt label
0 Available
I've tried with following linq query but it is returning 0 count and hence result is not being retrieved.
var data = (from a in context
where a.date = System.DateTime.Now
group a in a.id into g
select new {
cnt = g.Count(),
label = 'Available'
}).ToList();
How do I achieve above mentioned result in linq. Your help will be appreciated.
Thanks
-------------EDIT----------------
Updated LINQ query
var data = (from a in context.TableA
where a.id = uniqueID
group a in a.id into g
select new {
cnt = g.Count(),
label = 'Available'
}).Concat(from a in context.TableB
where a.id = uniqueID
group a in a.id into g
select new {
cnt = g.Count(),
label = 'WIP'
}).ToList();
To count the number of elements matching a predicate in a linq query simply use the where clause:
var results =
from a in context
where a.date.Date == DateTime.Now.Date
&& a.id == someIdHere
select a;
var data = new {
count = results.Count(),
label = "Available"
};
Or, in extension method syntax (which I prefer):
var results = context.Where(a => a.date.Date == DateTime.Now.Date && a.id == someIdHere);
var data = new {
count = results.Count(),
label = "Available"
};
Also be careful when comparing a DateTime object with regards to what results you desire; comparing DateTime.Now to a date will likley return false since it will compare the time code as well, use the DateTime.Date property to obtain only the date from the object for the purposes of comparison.

Linq filter out rows with null or string.empty

I have a linq query where I am reading all the lines of a CSV the file has extra rows at the end that have no data. I need to filter out those rows so that it only has the rows with data
I am using the following query but it still returns like 8000 rows and there are only 52 with data in them.
var query =
from c in
(from line in File.ReadAllLines(excelFile)
let transactionRecord = line.Split(',')
select new Transaction()
{
TxnId = transactionRecord[12],
})
where c.TxnTax != string.Empty
select c;
Not relaly sure why this is happening? Doe anyone have any ideas?
This will give an IEnumerable containing the lines (string[]) having at least one column with data
IEnumerable<string[]> data =
from line in System.IO.File.ReadAllLines("")
let lineData = line.Split(',')
where lineData.Any(cell => !string.IsNullOrEmpty(cell))
select lineData;
This worked
var query =
from c in
(from line in File.ReadAllLines(excelFile)
let transactionRecord = line.Split(',')
select new Transaction()
{
TxnId = transactionRecord[12],
})
where ((string.IsNullOrEmpty(c.TxnId) == false) && (c.TxnId != "Billing Information|Transaction ID"))
select c;

fill linq null data c# from previous line

I have bill details in list which contains the heading:
Account Numbers, Dates, Service Number, Charge category, Details, exgst, ingst, Detailsfill
Column :- Account Numbers, Dates, Service Number, Charge category, Details, exgst, ingst
are unique values but Column Detailsfill contains null. I want to allow my C# script to set values for Detailsfill where Detailsfill is null then insert data from previous row otherwise do nothing.
Note that Running total sets to 1 when detailsfill column has any text but continues to increment by 1 from 3 when detailsfill column is empty.
Below is the script I used.
var result_set2 = (from a in result_set1
join b in
(from x in result_set1a select x)
on
new {col1 = a.id, col2 = a.account, col3 = a.date, col4 = a.service, col5 = a.chargecat }
equals
new { col1 = b.id, col2 = b.account, col3 = b.date, col4 = b.service, col5 = b.chargecat } into outer
from tb in outer.DefaultIfEmpty()
where a.running_total1 != 0
where a.running_total1 != 2
where a.chargecat != ""
select new
{
running_total = a.running_total1,
account = a.account,
date = a.date,
service = a.service,
chargecat = a.chargecat,
details = a.details,
exgst = a.exgst,
ingst = a.ingst,
detailsfill = ((tb == null) ? "" : tb.details)
}).ToList();
foreach (var line in result_set2)
{
mobilenet_writerfile.WriteLine(line);
}
It sounds to me like you need a correlated subquery to populate detailsfill. This would be in the form of a select from a context with whatever parameters you determine fulfill your requirements. Example on second post of this thread: http://social.msdn.microsoft.com/forums/en-US/linqprojectgeneral/thread/18da37b0-b40e-444e-8ec7-7bd343e0c799/
Also you can find other examples here on stackoverflow: Is it possible to create a correlated subquery in LINQ?
More information would be required to write a contextual example but here is basically what it would look like:
Entities context = new Entities();
context.tbl.Where(t=>t.Id == someId)
.Select(t=> new() {
t.Id,
context.tbl2.First(tbl2=>tbl2.Id == t.Id).Value, //This is the subquery
t.whatever});
This is not a normal operation of Linq to hold onto a previous value and then use it later. That's not to say you can't make that work with Linq, but it would be more straightforward to keep that logic outside of the sequence operation. Simply iterate over the results after the query is composed.
var item = results.First();
foreach (var obj in results)
{
if (obj.detailsfill == null)
obj.detailsfill = item.detailsfill;
item = obj;
}
Note: If the first item happens to contain null in detailsfill, you will not pick up a value until the first item in the sequence that does contain a value. To get the first such item up front, simply use
var item = results.First(o => o.detailsfill != null);
// loop below

taking more than one cells into one cell

I am using a linq query to obtain a table of customers with their total money amount for each monetary unit exist in my database(this one is ok.)
when show the result of my query with Microsoft Report Viewer the result is like Table 1 but what i want is Table 2, only the customer name like "A" and a cell with all the monetory unit records > 0.
Is there any way you can suggest?
This is my code which produces Table 1:
var query = from kur in kurToplamlist
join cariBilg in db.TBLP1CARIs
on kur.CariIdGetSet equals cariBilg.ID
select new
{
cariBilg.ID,//customerid
EUROBAKIYE = cariBilg.HESAPADI,
cariBilg.K_FIRMAADI,//other column names
cariBilg.K_YETKILIADI,//other column names
cariBilg.K_FIRMATELEFON,//other column names
cariBilg.K_YETKILITELEFON,//other column names
AUDBAKIYE = cariBilg.B_CEPTELEFON,//other column names
MonetaryUnit = String.Concat(kur.KurToplamMiktarGetSet.ToString(), kur.DovizTuruGetSet.ToString()),//concatenates "100" and "TL/USD etc."
};
What i want is to obtain Table 2 in the image
Thank you in advance.
Table image
var query = from kur in kurToplamlist
where kur.KurToplamMiktarGetSet > 0
join cariBilg in db.TBLP1CARIs
on kur.CariIdGetSet equals cariBilg.ID
select new
{
cariBilg.ID,
EUROBAKIYE = cariBilg.HESAPADI,
cariBilg.K_FIRMAADI,
cariBilg.K_YETKILIADI,
cariBilg.K_FIRMATELEFON,
cariBilg.K_YETKILITELEFON,
AUDBAKIYE = cariBilg.B_CEPTELEFON,
TLBAKIYE = String.Concat(kur.KurToplamMiktarGetSet.ToString(), kur.DovizTuruGetSet.ToString()),
};
var dfg = from qre in query
select qre.TLBAKIYE;
var aq = (from qw in query
select new {
qw.ID,
EUROBAKIYE = qw.EUROBAKIYE,
qw.K_FIRMAADI,
qw.K_YETKILIADI,
qw.K_FIRMATELEFON,
qw.K_YETKILITELEFON,
AUDBAKIYE = qw.AUDBAKIYE,
TLBAKIYE = String.Join(",", (from qre in query
where qre.ID == qw.ID
select qre.TLBAKIYE).Distinct())
}).Distinct();
return aq;
This is my answer.

LINQ Having Clause with inner select

How would the following be converted to LINQ-EF
select Name
from TableA as TableAOuter
group by TableAOuter.Name, TableAOuter.Id
having(
select count(TableAInner.Id)
from TableA as TableAInner
where TAbleAInner.Reference=TableAOuter.Id) = 0
);
To me, that looks like:
var query = from row in tableOuter
group row by new { row.Name, row.Id } into g
where !tableInner.Any(inner => inner.Reference == g.Key.Id)
select g.Key.Name;
Although I'd be tempted to perform the filtering before the grouping - at which point you can just group the row name:
var query = from row in tableOuter
where !tableInner.Any(row => inner.Reference == row.Id)
group row.Name by new { row.Name, row.Id };
I think that should do the same thing, right?

Categories