Linq to SQL, contains in where clause repeated values - c#

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

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()
));

LINQ select new with collection

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.

Remove certain records from a set of records using LINQ

Question - how to remove certain records from LINQ, like i have some records i wanted them to be removed from my LINQ.
Scenario - i have table A with 10 records and table B with 2 records i want to remove records that are belong to B to be removed from A [using linq]
-below i have all the records in q and i want to remove the records that are there in p.
var p = from c in q
join dr in dc.TableData on c.Id equals dr.CaseId
select new View()
{
ActiveCaseId = c.ActiveCaseId,
Id = c.Id
};
q = q.Except(p);
You can't do it with the Except as you show, because p and q are different types. But it would also be a bit clumsy.
You can do it in one query:
var p = from c in q
where !dc.TableData.Any(dr => dr.CaseId == c.Id)
select new View()
{
ActiveCaseId = c.ActiveCaseId,
Id = c.Id
};

In the entity framework, how would you do an "IN" query on a joined table?

I'm a SQL junkie, and the syntax of the EF is not intuitive to me.
I have a Restaurant table and a Food table. I want the restaurants and foods where the foods have a type contained in the string list Categories. Here is some SQL that roughly represents what I want.
SELECT r.*, f.*
FROM Restaurant R
JOIN food f on f.RestaurantID = r.RestaurantID
WHERE f.Type IN ("Awesome", "Good", "Burrito")
Here's the code I want to turn into that SQL.
List<string> types = new List<string>() { "Awesome", "Good", "Burrito"};
var dbrestaurants = from d in db.Restaurants
.Include("Food")
//where Food.Categories.Contains(types)//what to put here?
select d;
Try
var restaurants = db.Restaurants.Where(r => types.Contains(r.Food.Type));
where Food.Categories.Any(c => types.Contains(c.Name))
Try this:
var dbRestaurants =
from r in db.Restaurants
join f in db.Foods on r.RestaurantId equals f.RestaurantId
where types.Any(foodType => foodType == f.Type)
select r;

nested linq queries, how to get distinct values?

table data of 2 columns "category" and "subcategory"
i want to get a collection of "category", [subcategories]
using code below i get duplicates. Puting .Distinct() after outer "from" does not help much. What do i miss?
var rootcategories = (from p in sr.products
orderby p.category
select new
{
category = p.category,
subcategories = (
from p2 in sr.products
where p2.category == p.category
select p2.subcategory).Distinct()
}).Distinct();
sr.products looks like this
category subcategory
----------------------
cat1 subcat1
cat1 subcat2
cat2 subcat3
cat2 subcat3
what i get in results is
cat1, [subcat1,subcat2]
cat1, [subcat1,subcat2]
but i only want one entry
solved my problem with this code:
var rootcategories2 = (from p in sr.products
group p.subcategory by p.category into subcats
select subcats);
now maybe it is time to think of what was the right question.. (-:
solved with this code
var rootcategories2 = (from p in sr.products
group p.subcategory by p.category into subcats
select subcats);
thanks everyone
I think you need 2 "Distinct()" calls, one for the main categories and another for the subcategories.
This should work for you:
var mainCategories = (from p in products select p.category).Distinct();
var rootCategories =
from c in mainCategories
select new {
category = c,
subcategories = (from p in products
where p.category == c
select p.subcategory).Distinct()
};
The algorithm behind Distinct() needs a way to tell if 2 objects in the source IEnumerable are equal.
The default method for that is to compare 2 objects by their reference and therefore its likely that no 2 objects are "equal" since you are creating them with the "new" keyword.
What you have to do is to write a custom class which implements IEnumerable and pass that to the Distinct() call.
Your main query is on Products, so you're going to get records for each product. Switch it around so you're querying on Category, but filtering on Product.Category

Categories

Resources