join list with linq-to-sql query - c#

I have list of MyObject that looks like this:
public class MyObject{
public int FruitID {get;set;}
public string FruitName {get;set;}
}
List<MyObject> TheList = new List<MyObject>();
This list is populated with a linq-to-sql query. I'm looking to create a join between this list and a table that contains FruitID as its foreign key.
The table HarvestTimes looks like this:
FruitID | HarvestDatetime | RipeFactor
3 | 3/4/2011 | 2
3 | 4/5/2011 | 4
3 | 5/5/2011 | 3
4 | 3/21/2011 | 2
4 | 4/10/2011 | 2
4 | 5/10/2011 | 2
This is what I have so far:
var TheQuery = (from list in TheList
join fruit in MyDC.HarvestTimes on
list.FruitID equals fruit.FruitID
where ....
select new MyObject{... }).ToList();
I'm have some trouble with the Where clause. How do I get only the Fruit where the RipeFactor was always 2. For instance, Fruit 3 has a RipeFactor of 2 but also has 4 and whereas only Fruit4 has only 2s. I tried with Contains but both fruits come up.
Thanks for your suggestions.

Assuming there is a Relationship between the tables HaverstTime and Fruit:
var TheQuery = MyDC.HarvestTimes
.Where(p => TheList.Select(q => q.FruitID).Contains(p.FruitID))
.GroupBy(p => p.Fruit)
.Where(p => p.All(q => q.RipeFactor == 2))
.Select(p => p.Key);
This will create a IEnumerable<Fruit> which I think can be easily converted to MyObject.
Update:
Oops I forgot to add TheList.Select(q => q.FruitID). That's why it didn't compile.
Sorry =)
Update2:
Do the same, considering Ripefactor = 2 and 3
var TheQuery = MyDC.HarvestTimes
.Where(p => TheList.Select(q => q.FruitID).Contains(p.FruitID))
.GroupBy(p => p.Fruit)
.Where(p => p.All(q => q.RipeFactor == 2 || q.RipeFactor == 3))
.Select(p => p.Key);

I think this would work
var fruit = (from list in TheList
join fruit in
(from fr in MyDc.HarvestTimes
group fr by fr.FruitID into fg
where !fg.Any(f => f.RipeFactor != 2)
select fg)
on list.FruitID equals fruit.Key
select new MyObject{... }).ToList();
Update - If you only want to return the distinct list of FruitIDs you need to select fg.Key instead of fg
var fruit = (from list in TheList
join fruit in
(from fr in MyDc.HarvestTimes
group fr by fr.FruitID into fg
where !fg.Any(f => f.RipeFactor != 2)
select fg.Key)
on list.FruitID equals fruit
select new MyObject{... }).ToList();

Related

Successive SelectMany in Linq Request

I have three tables built with EF code first.
I try to retrieve some information with SelectMany so that I can flatten the query and get only the fields that I need among those three tables.
My tables are presented as follow:
Tables: ProductOptions *-* ProductOptionValues 1-* LanguageProductOptionValue
|ProductOptionID | OVPriceOffset | LanguagesListID
|PriceOffset | OptionValueCategory | ProductOptionValueName
| | ... |
var queryCabColor = _db.ProductOptions
.Where(c => c.ProductOptionTypeID == 18 && c.ProductId == 1)
.SelectMany(z => z.ProductOptionValues, (productOptions, productOptionValues)
=> new
{
productOptions.ProductOptionID,
productOptions.PriceOffset,
productOptionValues.OVPriceOffset,
productOptionValues.OptionValueCategory,
productOptionValues.ProductOptionValuesID,
productOptionValues.Value,
productOptionValues.LanguageProductOptionValue
})
.SelectMany(d => d.LanguageProductOptionValue, (productOptionValues, productOptionValuesTranslation)
=> new
{
productOptionValuesTranslation.LanguagesListID,
productOptionValuesTranslation.ProductOptionValueName
})
.Where(y => y.LanguagesListID == currentCulture);
So far, when I loop in the query I can just retrieve the LanguagesListID and ProductOptionValueName and I can't find a way to get all of the above mentionned fields. Any suggestion?
I think in your case the Linq syntax is more appropriate than explicit SelectMany. Something like this should work:
var queryCabColor =
from productOptions in db.ProductOptions
where productOptions.ProductOptionTypeID == 18 && productOptions.ProductId == 1
from productOptionValues in productOptions.ProductOptionValues
from productOptionValuesTranslation in productOptionValues.LanguageProductOptionValue
where productOptionValuesTranslation.LanguagesListID == currentCulture
select new
{
productOptions.ProductOptionID,
productOptions.PriceOffset,
productOptionValues.OVPriceOffset,
productOptionValues.OptionValueCategory,
productOptionValues.ProductOptionValuesID,
productOptionValues.Value,
productOptionValuesTranslation.LanguagesListID,
productOptionValuesTranslation.ProductOptionValueName
};

Linq Group by Values in a list

So Currently I have this TrackingInfo class which contains an ID and a list of EmailActionIDs, which is an int.
I have a List Of this class which the data looks like:
ID, | EmailActions
_______________
A | 1, 3, 5
B | 3, 5, 6
C | 2, 4, 6
I'm trying to write a Linq Statement To convert this into A list of IDs grouped by each individual value in the list.
So the Results Set would look like:
ID | Values
_______________
1 | A
2 | C
3 | A, B
4 | C,
5 | A, B
6 | B, C
I can't figure out how I would write the group by can anyone give me some insight.
DistinctValues = new List<int> {1,2,3,4,5,6};
TrackingInfo.Groupby(t => DistinctValues.foreach(d =>
t.EmailActions.Contains(d))).Tolist()
This ofcourse isn't working any suggestions on how to do this using Linq
Its easy enough to get a distinct list of EmailActions
var distinctEmailActions = items.SelectMany(i => i.EmailActions).Distinct();
Then pivoting this is a little complex, but here it is:
var result = distinctEmailActions.Select(e => new {
ID=e,
Values = items.Where(i => i.EmailActions.Contains(e)).Select(i => i.ID)
});
Live example: http://rextester.com/CQFDY66608
What you're looking for is SelectMany, but it's easier to use query syntax here:
var result = from item in source
from action in item.EmailActions
group item.ID by action into g
select new { ID = g.Key, Values = g.ToList() }
You can do it by first generating a range using Enumerable.Range, and then matching EmailActions, like this:
var res = Enumerable.Range(1, 6)
.SelectMany(v => TrackingInfo.Where(info => info.EmailActions.Contains(v)).Select(info => new { Id, Value = v }))
.GroupBy(p => p.Value)
.Select(g => new {
Id = g.Key
, Values = g.Select(p => p.Id).ToList()
});
You can achieve this using SelectMany & GroupBy like this:-
var result = tracking.SelectMany(x => x.EmailActionIDs,
(trackObj, EmailIds) => new { trackObj, EmailIds })
.GroupBy(x => x.EmailIds)
.Select(x => new
{
ID = x.Key,
Values = String.Join(",", x.Select(z => z.trackObj.ID))
}).OrderBy(x => x.ID);
Working Fiddle.

Linq to SQL | Get all records where a foreign key doesn't exist

I have 2 tables:
Schools
-------
pk_school_id,
title
and
Business_Hours
--------------
pk_id,
fk_school_id
I want pk_school_id and title from School Table for all pk_school_id that does not exist as fk_school_id in Business_Hours table.
var Schools = (from b in Db.Language_School_Business_Hours
join s in Db.Language_Schools on b.fk_school_id equals s.pk_school_id into lrs
from lr in lrs.DefaultIfEmpty()
select new
{
LeftID = b.fk_school_id,
RightId = ((b.fk_school_id == lr.pk_school_id) ? lr.pk_school_id : 0)
});
try this to achieve your goal, without join, just take elements that are not contained in Business_Hours table
var Schools = Db.Language_Schools
.Where(s => !Db.Language_School_Business_Hours
.Select(b => b.fk_school_id).ToList().Contains(s.pk_school_id))
.Select(x => new
{
x.pk_school_id,
x.school_title
});
I think we can a bit simplify the linq by removing .ToList() after the first .Select(...), removing the last .Select(...). Pls take a look at a below code.
var schools = Db.Language_Schools
.Where(w => !Db.Language_School_Business_Hours
.Select(s => s.fk_school_id)
.Contains(w.pk_school_id))
.ToList();

Group by with static columns and grouped columns

I'm use to sql, and not quite used to linq yet. May I ask how do I group columns based on a value, and group other columns to a list and make the other columns static?
For Example
People | Businesses | StreetAddress
John | Store 1 | Hello Blvd.
John | Store 2 | Hello Blvd.
Produces
People | Businesses | StreetAddress
John | ["Store 1", "Store 2"] | Hello Blvd.
My linq query to make Table 1
from x in ctx.People
join ownership in ctx.Ownerships
on x.Id equals ownership.Owner_Id into ps
from ownership in ps.DefaultIfEmpty()
join Business in ctx.Businesses
on ownership.Business_Id equals Business.Id into ps2
from Business in ps2.DefaultIfEmpty()
select new PersonDTO
{
Id = x.Id,
Business = Business.Name,
StreetAddress = x.Addresses.FirstOrDefault().Line1
}
Assuming you need to group by both People & StreetAddress.
var result = data.GroupBy(x => new { x.People, x.StreetAddress })
.ToList()
.Select(x => new
{
People = x.Key.People,
Business = String.Join(",",x.Select(z => z.Business),
StreetAddress x.Key.StreetAddress
});
Edit:
Fetch Business in a List.
var result = data.GroupBy(x => new { x.People, x.StreetAddress })
.Select(x => new
{
People = x.Key.People,
Business = x.Select(z => z.Business).ToList(),
StreetAddress x.Key.StreetAddress
});
Here, data is the data source you want to group.

Remove Duplicate based on column value-linq

i have many to many relationship between employee and group. following linq statement
int[] GroupIDs = {6,7};
var result = from g in umGroups
join empGroup in umEmployeeGroups on g.GroupID equals empGroup.GroupID
where GroupIDs.Contains(g.GroupID)
select new { GrpId = g.GroupID,EmployeeID = empGroup.EmployeeID };
returns groupid and the employeeid. and result is
GrpId | EmployeeID
6 | 18
6 | 20
7 | 19
7 | 20
I need to remove the rows for which the employeeid is repeating e.g. any one of the row with employeeid= 20
Thanks
Okay, if you don't care which employee is removed, you could try something like:
var result = query.GroupBy(x => x.EmployeeId)
.Select(group => group.First());
You haven't specified whether this is in LINQ to SQL, LINQ to Objects or something else... I don't know what the SQL translation of this would be. If you're dealing with a relatively small amount of data you could always force this last bit to be in-process:
var result = query.AsEnumerable()
.GroupBy(x => x.EmployeeId)
.Select(group => group.First());
At that point you could actually use MoreLINQ which has a handy DistinctBy method:
var result = query.AsEnumerable()
.DistinctBy(x => x.EmployeeId);

Categories

Resources