Reputation: 1656
public Team getTeamByID(int id)
{
Team team = ctx.Teams.Include("Login").Include("People").Include("School").Where(x => x.id == id && this.schoolsList.Contains(x.school_id)).FirstOrDefault();
///
}
ctx
is a DataAccess
obbject and schoolsList
is a DataAccess
property of type List
. I understsand the part that says x => x.id == id
, but the part where this.schoolsList.Contains(x.school_id)
makes no sense to me. I know x => x.id == id
returns Team objects that match the id passed in as an argument, but how exactly does this.schoolsList.Contains(x.school_id)
work? How can I be able to use school_id
property (which is a property of the Team class)?
Is the first part of the predicate (x => x.id == id
) returning the Team Object, and then the second part is using the returned object's school id? For some reason that seems like a weird way for things to be working since I kinda thought everything in the Where()
method taken together returned something, instead of each condition returning something.
Upvotes: 1
Views: 65
Reputation: 2972
Team team = ctx.Teams
.Include("Login")
.Include("People")
.Include("School")
.Where(x => x.id == id
&& this.schoolsList.Contains(x.school_id))
.FirstOrDefault();
With this line you are retrieving the first element of ctx.Teams
that meets the requirements imposed by the Where
clause
ctx.Teams
Here you calling the table Teams
from the database through ctx
The Include
statements are used to join other tables like a Join in SQL and retrieves the data within the joined table.
.Where(x => x.id == id
&& this.schoolsList.Contains(x.school_id))
Here you are filtering the table data where the line has the id from the variable id
and is inside schoolsList
.
FirstOrDefault();
this retrieves the first item inside the IQueryable
returned by the Where
clause.
This can also be translated to:
Team team = ctx.Teams
.Include(x => x.Login)
.Include(x => x.People)
.Include(x => x.School)
.FirstOrDefault(x => x.id == id
&& this.schoolsList.Contains(x.school_id));
Includes written like this are less buggy like and more OOP. To do this you need the following namespace System.Data.Entity
.
** EDIT 1 **
I sort of understand but not completely. How does it know what x.school_id is? I thought I had included it in my question, but I just edited it in, and the only argument passed into that function was "id." So where exactly is the value of x.school_id passed into Contains coming from? Is it from the Team object that is returned from the condition x.id == id? – FrostyStraw
Because the Where
clause or FirstOrDefault
does a iteration with SQL through ctx.Teams
where the class of Teams
contains the property school_id
.
This is only possible with EntityFramework, where a table is represented by a class and the class properties are table Columns.
Ah! and when you do this.schoolsList.Contains(x.school_id)
you are calling the list schoolsList
on each "SQL Iteration" caused by Where
.
It's like doing:
List<Team> teams = ctx.Teams
.Include("Login")
.Include("People")
.Include("School")
.ToList();
Team team = null;
foreach (var item in teams)
{
if (item.id == id && this.schoolsList.Contains(item.school_id))
{
team = item;
break;
}
}
Upvotes: 2
Reputation: 3791
.Can someone help me understand the following line?
It does invoke Include()
method several times, which returns this
(same object), so it can invoke it again.
Then it uses LINQ query (seems IEnumerable<> inherited) to find specific element by condition in lambda.
FirstOrDefault()
returns first matching element (if any) or null
(default(T)
). Answering your original question.
Lambda condition is a simple if
expression for IEnumerable
items. Lambda gets invoked to return true
or false
each time FirstOrDefault()
will enumerate internal array to determine if item matches or not.
Upvotes: 1
Reputation: 7447
The contains method is translated into SQL with the IN clause. suppose the list contains 3 items 1,2,3 then it translates into
where team.school_id in (1,2,3)
Take a look at the generated sql, for instance intellisense shows it if you have VS ultimate, and things will become understandable. Otherwise look at this How do I view the SQL generated by the Entity Framework?
I have done this with an example of myself :
string[] roles = {"admin","medewerker"};
_medewerkers = contactPersoonRepository
.Query(c => c.Bedrijf.BEDRIJF_TYPE.Contains("P") && roles.Contains(c.CP_ROLE))
.NoTracking()
.OrderBy(q => q.OrderBy(d => d.CP_NAAM))
.Select(b => new Medewerker
{
Naam = b.CP_NAAM,
VoorNaam = b.CP_VOORNM,
Id = b.CP_CPID,
Rol = b.CP_ROLE,
Uurloon = b.CP_UURLOON
}).ToList();
translates into
USE [Jogical];
GO
SELECT
[Extent1].[CP_CPID] AS [CP_CPID],
[Extent1].[CP_NAAM] AS [CP_NAAM],
[Extent1].[CP_VOORNM] AS [CP_VOORNM],
[Extent1].[CP_ROLE] AS [CP_ROLE],
[Extent1].[CP_UURLOON] AS [CP_UURLOON]
FROM [dbo].[ContactPersoon] AS [Extent1]
INNER JOIN [dbo].[Bedrijf] AS [Extent2] ON [Extent1].[CP_BEDRIJFID] = [Extent2].[BEDRIJF_ID]
WHERE ([Extent2].[BEDRIJF_TYPE] LIKE N'%P%') AND ([Extent1].[CP_ROLE] IN (N'admin', N'medewerker')) AND ([Extent1].[CP_ROLE] IS NOT NULL)
ORDER BY [Extent1].[CP_NAAM] ASC
The relevant part is this :
([Extent1].[CP_ROLE] IN (N'admin', N'medewerker'))
Which comes from the contains call.
Notice how the contains is translated differently when applied on a string. Isn't EF great ;-)
Upvotes: 2