Which way will get high performance while selecting many data IQueryable Vs For loop (Using Entity Frame Work) - linq

I am trying to get a list from the database containing two or more lists inside that list.(using .net core, entity framework).Assume I have two table call header and details table.
Header Table
Detail Table
And I want the result like this:
{
"data":[
{
"Country":"Singapore",
"Hospital_List":[
{
"Hospital_Name":"SG Host A"
},
{
"Hospital_Name":"SG Host A"
}
]
},
{
}
]
}
I only know two ways to get the result like this,First Way, select Country list data with blank Hospital list as List,then for loop that list to select related Hospital list from db again.
And Second Way,select Country list data with blank Hospital list as IQueryable List,and then select related Hospital list via jointing with Hospital Table.So my question is
Which way should i used to get higher performance? And Is any other way?
Please remember there has a lot of field and data in my real table.

For loop give give you the lowest perfomance, because you will create SQL query for each iteration. Instead of this, try following solution:
from hospital in hospitals
group hospital by hospital.CID into gh
join country in countries
on gh.FirstOrDefault().CID equals country.CID
select new
{
Country = country.Country,
Hospital_List = from h in gh select h
}
EDITED:
And if your model created right you can use this code:
from hospital in hospitals
join country in countries
on hospital.Country equals country
group hospital by hospital.CID into gh
select new
{
Country = from h in gh select h.Country.Country,
Hospital_List = from h in gh select h
}

Related

Joining with linq

I have the following linq statement. It is returning everything from allStores. I removed the DefaultIfEmpty and then it only returned the stores that are in both the subs table AND the allStores table. I need it to return all stores that are in subs table even if they are not in the allStores table. I have tried a few different things and have moved around the defaultifempty but can't seem to get it to return what I need.
I need stores 1,2,4,5 returned (everything in table 2) and I need to pull the division ID for the storeId from table 3 and the address from table 3. Even if the store is not in the address table or not in divisionID table I still need the storeID returned in the query.
from a in allStores
join sub in subs on a.DivisionId equals sub.DivisionId
join d in divs on new { a.DivisionId, a.StoreId } equals new { d.DivisionId, d.StoreId } into s
from selected in s.DefaultIfEmpty()
StoreId
Address
1
1234 Elm St.
2
5678 Maple St.
3
9101 Bella Ave.
4
1234 Meadow Dr.
StoreId
StoreStatus
1
Closed
2
Open
4
Open
5
Open
StoreId
DivisionId
1
12
2
14
3
16
4
18
5
20
You're looking for multiple left joins. I've noticed that in this area of questions there are a lot of near duplicates. But many of these only discuss one left join, others don't describe a need to deal with null reference exceptions, and still others describe linq-to-sql or similar and not linq-to-objects, which seems to be your case here.
Your sample data is not complete, so I'm just going to trust that you are joining on the right fields. You're close with your join on divs. But you need to do the same thing for subs, and you need to add a select segment that outputs the final shape of each row extracting properties from each source.
var results =
from a in allStores
// left join allScores with "subs"
join sub in subs on a.DivisionId equals sub.DivisionId into subG
from sub in subG.DefaultIfEmpty()
// left join allScores with divs
join div in divs
on new { a.DivisonId, a.StoreId }
equals new { div.DivisionId, div.StoreId }
into divG
from div in divG.DefaultIfEmpty()
// select properties from all sources, keeping in mind some are null
select new {
a.StoreId,
a.StoreStatus,
sub?.Address, // if you have a newer version of c#
DivisonId = div == null ? null : (int?)div.DivisionId // if you have an older version of c#
};

Laravel eloquent deep count with relationship

I want to get count from deep table and the relationship is A->B->C->D and I want total count of D.
For example;
A: 3 Boss
B: 5 Managers
C: 8 Human Resources
D: 25 Employees
Imagine that every boss has managers and every manager has human resources and also every human resource has employees. How can I get total count every boss's employees' with Laravel. (For instance, first boss has 7 employees at the end.) Should I have to write hard sql code like joins or can I handle with eloquent?
By the way, my tables:
A: id, name
B: id, name
A and B has pivot table.
C: id, name
B and C has pivot table
D: id, name
C and D has pivot table
So far, I tried to:
$a = Boss::with("a.b.c.d")->where("id", 10)->first();
dd($a->b->c->d->count());
It just gave me d's count but I want to all of a's.
There is no native relationship for this case.
I created a HasManyThrough relationship with unlimited levels: Repository on GitHub
After the installation, you can use it like this:
class A extends Model {
use \Staudenmeir\EloquentHasManyDeep\HasRelationships;
public function d() {
return $this->hasManyDeep(D::class, ['a_b', B::class, 'b_c', C::class, 'c_d']);
}
}
$count = A::find($id)->d()->count();

Linq datatable to get unique rows and their count

i have data table like :
country
China
India
Thailand
India
china
china
Thailand
Hong kong
India
can get my output as shown below using LINQ
Country Count
India 3
China 2
Thailand 2
Hong kong 1
As Ben Allred pointed out, what you're likely looking for is the LINQ GroupBymethod.
Using query syntax, it may look something like this:
var query = from tuple in table
group tuple by tuple.Country into g
select new { Country = g.Key, Count = g.Count() };
query now contains an IEnumerable collection of anonymous objects which have as members the string Country and the integer Count representing the number of occurrences of that country in the table.
You can now of course iterate over these objects as such:
foreach (var item in query)
{
Console.WriteLine("Country : {0} - Count : {1}", item.Country, item.Count);
}
For more examples, I strongly suggest the 101 LINQ Samples
It's also worth pointing out if you haven't used LINQ before that the processing is deferred, meaning that the iteration over the query object doesn't occur until you try to access any of its items, for example, in the foreach statement. If the collection or reading from table is expensive and you intend to use the results of the query more than once, you can call ToList() on query to return a more tangible, concrete collection.

Get first record of each entity order by a column

I have a query in linq that fetch students assessments data something like
new {x.StudentId, x.StudentAssessmentId, x.AssessmentName, x.SubmittedDate}
then I perform some operations on this list to get only last added student assessment per student, I get last studentassessment by finding the max id of studentassessment,
so I finally get last studentassessments data of all the students.
Is there a way to do this directly in the initial list?
I thought about the way to group the results by student Id and select max of studentassessmentid, like
group x.StudentAssessmentId by x.StudentId
select new {x.Key, x.Max()}
in this way I will get student with there last studentassessmentid which is what I want but this will only give me studentassessment ids while I want other data also like AssessmentName, SubmittedDate etc.
Try something like this:
group x.StudentAssessmentId
by new {
x.StudentId,
x.AssessmentName,
x.SubmittedDate }
into g
select new
{
g.Key.StudentId,
g.Key.AssessmentName,
g.Key.SubmittedDate,
g.Max(),
}

Linq query returns duplicate results when .Distinct() isn't used - why?

When I use the following Linq query in LinqPad I get 25 results returned:
var result = (from l in LandlordPreferences
where l.Name == "Wants Student" && l.IsSelected == true
join t in Tenants on l.IsSelected equals t.IsStudent
select new { Tenant = t});
result.Dump();
When I add .Distinct() to the end I only get 5 results returned, so, I'm guessing I'm getting 5 instances of each result when the above is used.
I'm new to Linq, so I'm wondering if this is because of a poorly built query? Or is this the way Linq always behaves? Surely not - if I returned 500 rows with .Distinct(), does that mean without it there's 2,500 returned? Would this compromise performance?
It's a poorly built query.
You are joining LandlordPreferences with Tenants on a boolean value instead of a foreign key.
So, most likely, you have 5 selected land lords and 5 tenants that are students. Each student will be returned for each land lord: 5 x 5 = 25. This is a cartesian product and has nothing to do with LINQ. A similar query in SQL would behave the same.
If you would add the land lord to your result (select new { Tenant = t, Landlord = l }), you would see that no two results are actually the same.
If you can't fix the query somehow, Distinct is your only option.

Resources