How to select specific column in LINQ? - c#

I have to select specific column from my DataTable using linq
I am using this code
ds.Table[0].AsEnumerable().Where<DataRow>(r=>r.Field<int>("productID")==23).CopyToDataTable();
~
But it is giving me all columns and I need only PRODUCTNAME , DESCRIPTION , PRICE
How I can write this query?

To expand a bit on #lazyberezovsky, you can use an anonymous type projection to get all of the fields you want:
ds.Table[0].AsEnumerable()
.Where<DataRow>(r => r.Field<int>("productID") == 23)
.Select(r => new { ProductName = r.Field<string>("productName"),
Description = r.Field<string>("description"),
Price = r.Field<decimal>("price") });
I don't know what name and type your product name, description, and price fields are, so you will have to substitute those.

Use Select method:
ds.Table[0].AsEnumerable()
.Where<DataRow>(r=>r.Field<int>("productID")==23)
.Select(r => r.Field<int>("productID"));
UPDATE: In case you need to select several columns, you can return anonymous type:
var query = from row in dt.ds.Table[0].AsEnumerable()
where row.Field<int>("productID")==23
select new {
ProductID = x.Field<string>("productID"),
Foo = x.Field<string>("foo")
};
If you need to copy that data to new table, you'll face problem (CopyToDataTable requires collection of DataRow objects). See How to: Implement CopyToDataTable Where the Generic Type T Is Not a DataRow to solve this problem.

Related

Merg two list to get Third List both Lists Have two common and one different Column c#

I have two lists,
List <AgencyCount> Agency= AgencyList.ToList();
List<IndCount> Ind = individualList.ToList();
want to merge it into third list that is,
List<complain> list = new List<complain>();
Columns in Agency list,
CityId
CityNM
Acount
Columns in Ind list,
CityId
CityNM
Icount
Third list is using object of class type that is
CityId
CityNM
Acount
Icount
Values in the Agency and Ind list for the first two columns are same.
Resulting List get values for the first two column that is same and than get third column of both list as showns above.
Here is an example. As you said, that AgencyList and IndividualList has CityId and city_NM as common values, I'm assuming that the join of both lists are with these fields
The linq query returns an anonymous type, that you compose with fields from both lists. You can return a concrete object simply creating a new ResultClass and doing select new ReturnClass { in the linq
Updated as per #tsahi Asher comment
var qry = from a in AgencyList.ToList()
join i in individualList.ToList()
on a.CityId equals i.City_NM
select new {
a.yourField,
i.otherField
};
return qry.ToList();
#mnieto's answer was correct for the original question, which was completely rewritten (please don't do that, it leads to answers to non-existent questions like this). For the current version of the question, the answer is very similar, with only a different join condition:
var qry = from a in Agency
join i in Ind
on new { a.CityId, a.CityNM } equals new { i.CityId, i.CityNM }
select new {
a.CityId,
a.CityNM,
a.Acount,
i.Icount
};
return qry.ToList();

Sum and Group by in linq using Datarows

Full disclosure, I'm pretty much a total noob whe it comes to linq. I could be way of base on how i should be approaching this.
I have a DataTable with 3 columns
oid,idate,amount
each id has multiple dates, and each date has multiple amounts. What I need to do is sum the amount for each day for each id, so instead of:
id,date,amount
00045,02/13/2011,11.50
00045,02/14/2011,11.00
00045,02/14/2011,12.00
00045,02/15/2011,10.00
00045,02/15/2011,5.00
00045,02/15/2011,12.00
00054,02/13/2011,8.00
00054,02/13/2011,9.00
I would have:
id,date,SumOfAmounts
00045,02/13/2011,11.50
00045,02/14/2011,23.00
00045,02/15/2011,27.00
00054,02/13/2011,17.00
private void excelDaily_Copy_Into(DataTable copyFrom, DataTable copyTo)
{
var results = from row in copyFrom.AsEnumerable()
group row by new
{
oid = row["oid"],
idate = row["idate"]
} into n
select new
{
///unsure what to do
}
};
I've tried a dozen or so different ways of doing this and I always sort of hit a wall where i can't figure out how to progress. I've been all over stack overflow and the msdn and nothing so far has really helped me.
Thank you in advance!
You could try this:
var results = from row in copyFrom.AsEnumerable()
group row by new
{
oid = row.Field<int>("oid"),// Or string, depending what is the real type of your column
idate = row.Field<DateTime>("idate")
} into g
select new
{
g.Key.oid,
g.Key.idate,
SumOfAmounts=g.Sum(e=>e.Field<decimal>("amount"));
};
I suggest to use Field extension method which provides strongly-typed access to each of the column values in the specified row.
Although you don't specify it, apparently copyFrom is an object from a class DataTable that implements IEnumerable.
According to MSDN System.Data.DataTable the class does not implement it. If you use that class, you need property Rows, which returns a collections of rows that implements IEnumerable:
IEnumerable<DataRow> rows = copyFrom.Rows.Cast<DataRow>()
but if you use a different DataTable class, you'll probably do something similar to cast it to a sequence of DataRow.
An object of class System.Data.DataRow has item properties to access the columns in the row. In your case the column names are oid, idate and amount.
To convert your copyFrom to the sequence of items you want to do the processing on is:
var itemsToProcess = copyFrom.Rows.Cast<DataRow>()
.Select(row => new
{
Oid = row["oid"],
Date = (DateTime)row["idate"],
Amount = (decimal)row["amount"],
});
I'm not sure, but I assume that column idate contains dates and column amount contains some value. Feel free to use other types if your columns contain other types.
If your columns contain strings, convert them to the proper items using Parse:
var itemsToProcess = copyFrom.Rows.Cast<DataRow>()
.Select(row => new
{
Id = (string)row["oid"],
Date = DateTime.Parse( (string) row["idate"]),
Amount = Decimal.Parse (string) row["amount"]),
});
If you are unfamiliar with the lambda expressions. It helped me a lot to read it as follows:
itemsToProcess is a collection of items, taken from the collection of
DataRows, where from each row in this collection we created a new
object with three properties: Id = ...; Data = ...; Amount = ...
See
Explanation of Standard Linq oerations for Cast and Select
Anonymous Types
Now we have a sequence where we can compare dates and sum the amounts.
What you want, is to group all items in this sequence into groups with the same Id and Date. So you want a group where with Id = 00045 and Date = 02/13/2011, and a group with Id = 00045 and date = ,02/14/2011.
For this you use Enumerable.GroupBy. As the selector (= what have all items in one group in common) you use the combination of Id and Date:
var groups = itemsToProcess.GroupBy(item => new
{Id = item.Id, Data = item.Data} );
Now you have groups.
Each group has a property Key, of a type with two properties: Id and Data.
Each group is a sequence of items from your itemsToProcess collection (so it is an "itemToprocess" with Id / Data / Value properties)
all items in one group have the same Id and same Data.
So all you have to do is Sum all elements from the sequence in each group.
var resultSequence = groups.Select(groupItem => new
{
Id = groupItem.Key.Id
Date = groupItem.Key.Date,
Sum = groupItem.Sum(itemToProcess => itemToProcess.Value,
}
So putting it all together into one statement:
var resultSequence = copyFrom.Rows.Cast<DataRow>()
.Select(row => new
{
Id = (string)row["oid"],
Date = DateTime.Parse( (string) row["idate"]),
Amount = Decimal.Parse (string) row["amount"]),
})
.GroupBy (itemToProcess => new
{
Id = item.Id,
Data = item.Data
});
.Select(groupItem => new
{
Id = groupItem.Key.Id
Date = groupItem.Key.Date,
Sum = groupItem.Sum(itemToProcess => itemToProcess.Value,
});

Linq query how to select all columns

I have a linq query which is giving me desired output :
var data = (from c in dtskip.AsEnumerable()
select new[] {
c.Field<string>("Suburb"), c.Field<string>("Postcode"), c.Field<string>("State"),c.Field<string>("ID"), c.Field<string>("SEARCHKEY"), c.Field<string>("RATING"), c.Field<string>("DELIVERY")
});
How can i select all the column instead of giving name like c.field<string>("postcode") .My output is the data only from datatable dtskip :
output:
["DARWIN","0800","NT","2","DARWINNT","A","Delivery Area"]
,["ALAWA","0810","NT","5","ALAWANT","A","Delivery Area"],
["BRINKIN","0810","NT","6","BRINKINNT","A","Delivery Area"],
is there any other way i can get the output in dis way from datatable using linq query .
DataRow contains an ItemArray member which returns all the data in that row as an array, the downside is they are all returned as objects but if all your columns are the same type you can cast the ItemArray in line to the desired type (in this case string)
dtskip.Rows.Cast<DataRow>().Select(r => r.ItemArray.Cast<string>());
This will give you an IEnumerable<IEnumerable<string>> to work with.
have you tried
var data = (From c in dtskip
select c).AsEnumerable(); //Not sure about the AsEnumerable :s
Are you looking for something like this?
var data = dtskip.AsEnumerable().
Select(x => new
{
Suburb = x.Field<string>("Suburb"),
Postcode= x.Field<string>("Postcode"),
State= x.Field<string>("State"),
Id= x.Field<string>("ID"),
Searchkey = x.Field<string>("SEARCHKEY"),
Rating = x.Field<string>("RATING"),
Delivery = x.Field<string>("DELIVERY")
});

Use calculated / scalar value in LINQ query

I'm using LINQ on a Telerik OpenAccess generated data model, to setup a search query and get the results. This all works very well and the code looks very nice.
But now i need to add one more thing, and i'm not sure how to.
The products i'm selecting should have a different price for each customer. The price depends on some other values in 2 other SQL tables. Right now i have the price calculation in a SQL scalar function, but i'm not sure on how to use that in combination with my LINQ.
My goal is to retrieve all data in one database roundtrip, and to be able to sort on this calculated price column as well.
Right now i have something like:
var products = (from p in Products select p);
if(searchOption)
products = products.Where(product => product.Name.Contains(searchOption));
products = products.OrderByDescending(product => product.Name);
products = products.Skip(pageNr * pageSize).Take(pageSize);
I can, of course, use all properties of my Product class, but i want to be able to use a new virtual/calculated property, let say: Product.CalculatedPrice as well.
I have a feeling it should look a bit like this.
(from p in Products
select new {
productId = p.ProductId,
name = p.Name,
calculatedPrice = CalculatedValueFromStoredProcedure/OrScalarFunction(p.ProductId, loggedInCustomerId)
});
Best Regards, Tys
.Select() allows you to create a dynamic type, in which you can extend the product with the calculated price
products.Select(i => new { Product = i, CalculatedPrice = 100})
or in your initial line:
var products = (from p in Products select new { Product = p, CalculatedPrice = 100 });
After doing some more research i've found out that what i want to do is NOT possible in combination with the Telerik OpenAccess ORM! So i've created a workaround that pre-calculates the values i need, put them in a table and join my selection with the contents of that table.
For now, that's the best possible solution i've found.

Best method for programmatically requesting db table columns using LINQ

Is there a good way of requesting only specified columns from the database using LINQ? I want to be able to select only certain columns depending on arbitrary conditions from code.
You can create anonymous types for each condition, which contain only the columns you specify.
var anonymousType = from item in itemCollection
select new {Column1 = item.Column1, Column2 = item.Column2};
var anonymousType2 = from item in itemCollection
select new {Column2 = item.Column2, Column3 = item.Column3};
Not sure exactly what you mean.
Are you maybe wanting to pull different columns based on a conditional?
Something like this?
if(condition)
{
table.Select(x => x.ColumnA);
}
else
{
table.Select(x => x.ColumnB);
}

Categories

Resources