LINQ join multi tables in Lambda ex - linq

I hope that someone can help me out here or to point me in the right direction:
I have an issue with this script from my SQL. This is what I have from the database and it comes out with success.
Script for water counter that has reminder for active period:
Select *
from WaterCounters
join WaterUsages on WaterUsages.WaterCounterId = WaterCounters.Id
join Periodes per on per.PeriodeId=WaterUsages.PeriodeId
where per.IsApproved = 1
Now I am trying to "translate/convert" into a LINQ query:
var waterCounter = Context.MyWaterCounter.Join(xx).ToList...
I am sure that I am doing it right but please advice me in how to "join more than one table" - thanks in advance.
Best regards,
Kvolle
UPDATED:
this is my script so far:
var waterCounter = Context.MyWaterCounter.Join(
Context.MyWaterUsages
.Where(x => x.WaterCounterId ==x.WaterCounterId)
.ToList());
Here is as I see it one table.
The tables in the database look like this:

It will look something like below
var waterCounter = Context.MyWaterCounter.Join(
Context.MyWaterUsages,
(WC) => WC.WaterCounterId,
(WU) => WU.Id,
(WC, WU) => new { WaterCounter = WC, WaterUsage = WU}
)
.Join(
Context.Periodes.Where(p => p.IsApproved=1),
(WUC) => WUC.WaterUsage.PeriodeId,
(P) => P.PeriodeId,
(WUC, P) => new { WaterCounter = WUC.WaterCounter, WaterUsage = WUC.WaterUsage, Period = P}
)
.ToList());

Related

How to find all rows of items that have a part in common using LINQ?

I need to return all records (items) that has a part (X) so I can use that in a group or .GroupBy afterwards
Using this summary data:
ItemName PartName
1 A
1 B
2 A
3 C
So Item1 has two parts (A,B), etc...
I need a LINQ query that will
- find all items that have part A (i.e items 1 and 2)
- return all rows for all these items
1 A
1 B
2 A
Notice that the end result returned the row (1 B) because Item1 has PartA and so I need to get back all rows for Item1.
I was looking at something like:
let items = from data in summary where data.PartName == A select new { data.ItemName } // to get all the items I need
But then, now that I have that list I need to use it to get all the rows for all items listed, and I can't seem to figure it out ...
Actual Source Code (for reference):
NOTE:
Recipe = ITEM
Ingredient = PART
(I was just trying to make it simpler)
ViewFullRecipeGrouping = (
from data in ViewRecipeSummary
group data by data.RecipeName into recipeGroup
let fullIngredientGroups = recipeGroup.GroupBy(x => x.IngredientName)
select new ViewFullRecipe()
{
RecipeName = recipeGroup.Key,
RecipeIngredients = (
from ingredientGroup in fullIngredientGroups
select new GroupIngredient()
{
IngredientName = ingredientGroup.Key
}
).ToList(),
ViewGroupRecipes = (
from data in ViewRecipeSummary
// this is where I am looking to add the new logic to define something I can then use within the next select statement that has the right data based on the information I got earlier in this query.
let a = ViewRecipeSummary.GroupBy(x => x.RecipeName)
.Where(g => g.Any(x => x.IngredientName == recipeGroup.Key))
.Select(g => new ViewRecipe()
{
RecipeName = g.Key,
IngredientName = g.Select(x => x.IngredientName)
})
select new GroupRecipe()
{
// use the new stuff here
}).ToList(),
}).ToList();
Any help would be much appreciated.
Thanks,
I believe this does what you want:
var data = /* enumerable containing rows in your table */;
var part = "X";
var items = new HashSet<int>(data
.Where(x => x.PartName == part)
.Select(x => x.ItemName));
var query = data.Where(x => items.Contains(x.ItemName));
If I understand your comment at the end, I believe this also does what you want:
var query = data
.GroupBy(x => x.ItemName)
.Where(g => g.Any(x => x.PartName == part))
.Select(g => new
{
ItemName = g.Key,
PartNames = g.Select(x => x.PartName)
});

Linq, how to write regular query with aggregate function?

on my page, I need to show a list of tools.
var tools = _toolRepository.GetAll().Where(t => t.IsActive == true).OrderByDescending(t => t.PostDate).Take(50).ToList();
I also need to show how many Votes each tool got, I can write a separate query to do that, but that will double the number of queries.
is there a way to combine them together?
here's my database structure.
Tool
id
name
postDate
ToolVote
id
ToolId
UserId
How about:
var tools = _toolRepository.GetAll().Where(t => t.IsActive == true).OrderByDescending(t => t.PostDate).Take(50).Select(tool => new { Tool = tool, votes = ToolVotes.Where(tv => tv.ToolID == tool.ToolID)} ).ToList();
Assuming that you have 1 to * relationship you can use left join.
I can't test this query but it should look something like this
var query = (from tool in _toolRepository.GetAll().Where(t => t.IsActive == true).OrderByDescending(t => t.PostDate).Take(50)
join toolVote in toolVotes on tool.id equals toolVote.ToolId
into toolsTemp
from toolTemp in toolsTemp.DefaultIfEmpty()
select new { Tool = tool, Count = toolTemp == null ? 0 : toolTemp.Count})
.ToList();

LINQ Group By into a Dictionary Object

I am trying to use LINQ to create a Dictionary<string, List<CustomObject>> from a List<CustomObject>. I can get this to work using "var", but I don't want to use anonymous types. Here is what I have
var x = (from CustomObject o in ListOfCustomObjects
group o by o.PropertyName into t
select t.ToList());
I have also tried using Cast<>() from the LINQ library once I have x, but I get compile problems to the effect of it being an invalid cast.
Dictionary<string, List<CustomObject>> myDictionary = ListOfCustomObjects
.GroupBy(o => o.PropertyName)
.ToDictionary(g => g.Key, g => g.ToList());
I cannot comment on #Michael Blackburn, but I guess you got the downvote because the GroupBy is not necessary in this case.
Use it like:
var lookupOfCustomObjects = listOfCustomObjects.ToLookup(o=>o.PropertyName);
var listWithAllCustomObjectsWithPropertyName = lookupOfCustomObjects[propertyName]
Additionally, I've seen this perform way better than when using GroupBy().ToDictionary().
For #atari2600, this is what the answer would look like using ToLookup in lambda syntax:
var x = listOfCustomObjects
.GroupBy(o => o.PropertyName)
.ToLookup(customObject => customObject);
Basically, it takes the IGrouping and materializes it for you into a dictionary of lists, with the values of PropertyName as the key.
This might help you if you to Get a Count of words. if you want a key and a list of items just modify the code to have the value be group.ToList()
var s1 = "the best italian resturant enjoy the best pasta";
var D1Count = s1.ToLower().Split(' ').GroupBy(e => e).Select(group => new { key = group.Key, value = group.Count() }).ToDictionary(e => e.key, z => z.value);
//show the results
Console.WriteLine(D1Count["the"]);
foreach (var item in D1Count)
{
Console.WriteLine(item.Key +" "+ item.Value);
}
The following worked for me.
var temp = ctx.Set<DbTable>()
.GroupBy(g => new { g.id })
.ToDictionary(d => d.Key.id);

Groupby and where clause in Linq

I am a newbie to Linq. I am trying to write a linq query to get a min value from a set of records. I need to use groupby, where , select and min function in the same query but i am having issues when using group by clause. here is the query I wrote
var data =newTrips.groupby (x => x.TripPath.TripPathLink.Link.Road.Name)
.Where(x => x.TripPath.PathNumber == pathnum)
.Select(x => x.TripPath.TripPathLink.Link.Speed).Min();
I am not able to use group by and where together it keeps giving error .
My query should
Select all the values.
filter it through the where clause (pathnum).
Groupby the road Name
finally get the min value.
can some one tell me what i am doing wrong and how to achieve the desired result.
Thanks,
Pawan
It's a little tricky not knowing the relationships between the data, but I think (without trying it) that this should give you want you want -- the minimum speed per road by name. Note that it will result in a collection of anonymous objects with Name and Speed properties.
var data = newTrips.Where(x => x.TripPath.PathNumber == pathnum)
.Select(x => x.TripPath.TripPathLink.Link)
.GroupBy(x => x.Road.Name)
.Select(g => new { Name = g.Key, Speed = g.Min(l => l.Speed) } );
Since I think you want the Trip which has the minimum speed, rather than the speed, and I'm assuming a different data structure, I'll add to tvanfosson's answer:
var pathnum = 1;
var trips = from trip in newTrips
where trip.TripPath.PathNumber == pathnum
group trip by trip.TripPath.TripPathLink.Link.Road.Name into g
let minSpeed = g.Min(t => t.TripPath.TripPathLink.Link.Speed)
select new {
Name = g.Key,
Trip = g.Single(t => t.TripPath.TripPathLink.Link.Speed == minSpeed) };
foreach (var t in trips)
{
Console.WriteLine("Name = {0}, TripId = {1}", t.Name, t.Trip.TripId);
}

LINQ to SQL, select targets with max date

I ended up with this horrible code below, I can't get a better result now.
What is a better way of doing that?
It's about this part of my database:
EDIT
A Patient has a Subscription to multiple MonitoringObjects. Target records refer to these Subscriptions. I want to retrieve the target records with the newest date per Subscription for a given Patient and a Category of MonitoringObjects. These target records may have different max dates, as Targets can be added for Subscriptions to MonitoringsObjects independently.
var subs = db.Subscriptions.Where(p => p.PatientID == patID).Where(p => p.MonitoringObject.Category.Name == "Medication");
var targets1 = from t in db.Targets
where subs.Contains(t.Subscription)
select t;
var maxTa = from t in db.Targets
group t by t.SubscriptionID
into g
select new
{
Ky = g.Key,
Date = g.Max(p => p.Date)
};
var targets2 = from t in targets1
where maxTa.Select(p => p.Ky).Contains( t.SubscriptionID ) &&
maxTa.Select(p => p.Date).Contains( t.Date )
select t;
I am not exactly sure what this is trying to achieve, or what your datamodel looks like, but something like this?
var subs = db.Subscriptions.Where(p => p.PatientID == patID).Where(p => p.MonitoringObject.Category.Name == "Medication");
var targets = subs
.SelectMany(s => s.Targets)
.Where(t => t.Date == t.Subscription.Targets.Max(_t => _t.Date))

Resources