LINQ select new with collection - c#

Context
I am trying to get a list from select new:
var portfolioresult =
(from port in _context.Portfolio
join u in _context.Universe on port.CUSIP equals u.ID_CUSIP
join m in _context.MarketDataEvent on u.ID_CUSIP equals m.CUSIP_NUMBER_REALTIME
//select new { m, port.Name }).ToList();
select new ViewResult() { MarketDataEvents = m, PortfolioName = port.Name })
.ToList();
I want to get MarketDataEvents as List<MarketDataEvent>
Corresponding SQL query
SELECT me.*, p.Name FROM MarketDataEvent me
INNER JOIN universe u ON u.ID_CUSIP=me.CUSIP_NUMBER_REALTIME
INNER JOIN portfolio p ON p.CUSIp=me.CUSIP_NUMBER_REALTIME
Problem
I am not able to get a List inside select new. Is it possible to get something like this?
select new ViewResult() { MarketDataEvents = List<MarketDataEvents>, PortfolioName = port.Name })
Expected result
List<MarketDataEvents> "XYZ"
List<MarketDataEvents> "ABC"
Actual result
MarketDataEvent "XYZ
MarketDataEvent "XYZ"
MarketDataEvent "ABC"

Yes, it is possible:
var query =
from port in _context.Portfolio
select new ViewResult
{
MarketDataEvents =
(from u in _context.Universe.Where(u => port.CUSIP == u.ID_CUSIP)
join m in _context.MarketDataEvent on u.ID_CUSIP equals m.CUSIP_NUMBER_REALTIME
select m).ToList(),
PortfolioName = port.Name
};
var portfolioresult = query.ToList();

Essentially your m reference is out of scope. The input available to a select statement is only a single value out of the set available as a result of the select/joins you're looking at, which is why you don't see a list of all available from m, only a single value in each record.
Rather, you need to use a SelectMany since it'll expose an IEnumerable as the input to the function and you can split out the individual XYZ values out of that.

Related

Linq query select new with List

I'm doing a query which gets back the names of the buyers grouped by the brand of the products they have bought. So far I'm here
var query= from p in purchaseRepo.ReadAll()
join g in guitarRepo.ReadAll() on p.GuitarId equals g.Id
join b in brandRepo.ReadAll() on g.BrandId equals b.Id
group p by b.Id into grp
select new
{
grp.Key,
grp.SelectMany(t => t.BuyerName)
}
My problem is that I would like to have a List or an array of the buyer names declared in the select new part's body, but I can't get it to work.
EDIT:
I've given names for the fields is select new it looks like this:
select new
{
Brand=grp.Key,
Buyers=new List<string>()
};
Now I only need to know how to get the buyer names into the List.
The result should be something like this:
Brand1 --->List of buyer names
Pick one:
Linq offers the .ToList() method
Linq offers the .ToArray() method
Be a hero and implement your own method that accepts an IEnumerable<string> and returns a list populated with the string elements from that enumerable...
I've managed to get it working, thanks everyone for the help!
Here's my query for others struggling:
var asd = from p in purchaseRepo.ReadAll()
join g in guitarRepo.ReadAll() on p.GuitarId equals g.Id
join b in brandRepo.ReadAll() on g.BrandId equals b.Id
group p by b.Name into grp
select new
{
Brand = grp.Key,
Buyers = grp.Select(t=>t.BuyerName)
};
var result = asd
.Select(x => new KeyValuePair<string, List<string>>(
x.Brand,
x.Buyers.ToList()
));

#C Razor Join Data LINQ

Attempting to display a table with a join on the Rating
to the ID within the Ratings table. I'm hitting an issue with the join within my statement.
var Movie = from u in _context.Movie
join g in _context.Ratings
on u.Rating equals g.ID
select (a => new List
{
Ratings = u.Rating,
MovieRating = g.MovieRating
});
Movie = await Movie.ToListAsync();
The type of one of the expressions in the join clause is incorrect. Type inference failed in the call to 'Join'.
You have some weird syntax like (a => new List { ... Not sure where you are going with that.
Do you have a class named List? are you trying to get a List? Why is "a" in there...since it is not referenced anywhere. You also try to change the type of the Movie variable in your code, the var keyword doesn't work that way. On the first line, you assign a IQueryable< T> to it and later on you try to assign a List< T> to it.
try something like this:
var movieQuery = from u in _context.Movie
join g in _context.Ratings on u.Rating equals g.ID
select new
{
Ratings = u.Rating,
MovieRating = g.MovieRating
};
var movies = await movieQuery.ToListAsync(); // query will be executed here
The example code above uses an anonymous class as result so movies will be of type List< T> where T is an anonymous class, if you do have a class called List (for some reason) representing a single result item, then use
select new List { ...
instead of
select new { ...
and if you don't wanna split the query / actual list into 2 variables, you can do something like:
var movies = await (from u in _context.Movie
join g in _context.Ratings on u.Rating equals g.ID
select new
{
Ratings = u.Rating,
MovieRating = g.MovieRating
}).ToListAsync();

Linq to SQL, contains in where clause repeated values

I have a simple table of items, called "ITEMS":
id description
-- -----------
1 Something
2 Another thing
3 Best thing
I have a list of Int32 which are item IDs I'd like to show:
List<Int32> currentItemsCodes = new List<int>();
For this example currentItemsCodes contains 1,2,2,3
Currently I have this Linq-to-SQL:
var itemDescriptions = (from a in db.ITEMS
where currentItemsCodes.Contains(a.id)
select new {a.id, a.description});
What this returns is:
1,Something
2,Another thing
3,Best thing
I need to return two "Another things":
1,Something
2,Another thing
2,Another thing
3,Best thing
Or if currentItemsCodes was 3,3,3,3 I would need 4 x "Best thing" returned
You should do a inner join in linq to get what you are looking for. Use the below linq query to do that.
var itemDescriptions = (from a in db.ITEMS
join c in currentItemsCodes
on a.id equals c
select new {a.id, a.description});
You can use a join clause for that:
var itemDescriptions = (from item in db.ITEMS
join i in currentItemsCodes on item.id equals i
select new
{
id = item.id,
description = item.description
}).ToList();
Something like this?
var x = db.items;
var itemDescriptions = (from a in currentItemsCodes
select new {a, x[a].description});
As in Kris's comments substitute for [a] a method to access the items by id

Left outer join off of group by dataset using linq

I am attempting to write the following SQL as a linq query.
SELECT grp.OrganisationId,
grp.OrderCount,
organisations.Name
FROM (select OrganisationId,
count(*) as OrderCount
from orders
where 1 = 1
group by OrganisationId) grp
LEFT OUTER JOIN organisations on grp.OrganisationId = organisations.OrganisationId
WHERE 1 = 1
The where clauses are simplified for the benefit of the example.
I need to do this without the use of navigational properties.
This is my attempt:
var organisationQuery = ClientDBContext.Organisations.Where(x => true);
var orderGrouped = from order in ClientDBContext.Orders.Where(x => true)
group order by order.OrganisationId into grouping
select new { Id = grouping.Key.Value, OrderCount = grouping.Count() };
var orders = from og in orderGrouped
join org in organisationQuery on og.Id equals org.Id
select(x => new OrganisationOrdersReportPoco()
{
OrganisationNameThenCode = org.Name,
TotalOrders = og.OrderCount
});
But I am getting an error of...
Type inference failed in the call to 'Join'
From previous threads, I believe this is because I have "lost the join with order" (but I don't understand why that matters when I am creating a new recordset of Organisation, Count).
Thanks!
I understand you may believe navigation properties are the solution here, but if possible, please can we keep the discussion to the join off of the group by as this is the question I am trying to resolve.
You are mixing lambda and LINQ expressions. Change select to:
select new OrganisationOrdersReportPoco()
{
OrganisationNameThenCode = org.Name,
TotalOrders = og.OrderCount
};
If i understood your model correctly you could try this instead:
var orders = ClientDBContext.Organisations.Select(org => new OrganisationOrdersReportPoco
{
OrganisationNameThenCode = org.Name,
TotalOrders = org.Orders.Count()
}).ToList();

dynamic linq group by clause

I have multiple linq queries that retrieve the same data just at different grouping levels. (potentially 3 different levels). The linq query currently results in an enumerable list of a custom object. The items I don't understand or wonder if possible (to reduce redundant code):
can I make the following group by clause to be dynamic?
if so, can it dynamically populate my custom object group data when it is grouped at that level.
For instance:
var myReport_GroupProductLevel =
from r in mySum_GroupProductLevel
join pc in _myPlotCount on r.Strata equals pc.Strata
join acr in _myStrataAcres on pc.Strata equals acr.Strata
group new { r, pc, acr } by new { r.Strata, pc.Count, acr.Acres, r.GroupName, r.ProductName } into g
select new DataSummary
{
Strata = g.Key.Strata,
PlotCount = g.Key.Count,
Acres = g.Key.Acres,
ClassName = string.Empty,
GroupName = g.Key.GroupName,
ProductName = g.Key.ProductName,
TPAMEAN = g.Sum(x => x.r.TPA / x.pc.Count),
TPADEV = g.Select(x => x.r.TPA).StdDev(g.Key.Count)
};
If I wanted to group only by "GroupName" instead... I would rewrite the query. Issues I see are, if I'm grouping by a value then I need that value in the query (g.Key.GroupName); but since I'm creating a new custom object the other non-grouped values such as "ClassName" require a value (I used string.Empty above, but that is static).
Thanks for any insight...
if anyone was curious, I got it to work by using a conditional statement... since grouping by empty will make it collapse.
var mySum_ClassGroupProductLevel =
from s in ReportData.myStands
join p in ReportData.myPlots on s.ID equals p.StandID
join t in ReportData.myTrees on p.ID equals t.PlotID
group t by new { s.Strata, p.ID,
ClassName = useClassName ? t.ClassName : string.Empty,
GroupName = useGroupName ? t.GroupName : string.Empty,
ProductName = useProductName ? t.ProductName : string.Empty }
into g
select new
{}

Categories

Resources