You can try to rewrite the code with lambdas to code without lambdas (:
Do not make the mistake of asserting that the presence of lambdas implies the absence of LINQ expressions. Remember that the extension methods Select
, Where
, among others, are all part of LINQ; The great detail is that in one case you can use these methods in a style similar to SQL and in another case they are used as a cascade call of the different extension methods. Whatever the case, the MSIL code generated when compiling is practically the same, which is expressed as a cascade call of the different extension methods.
Based on the LINQ code with lambdas, as in the question:
var cursos_tomados = ctx.AlumnoCurso.Where(x => x.Alumno_id == ((Alumno_id)))
.Select(x => x.Curso_id)
.ToList();
cursos = ctx.Curso.Where(x => !cursos_tomados.Contains(x.id)).ToList();
As written, Alumno_id
(in double parentheses) is a variable whose value is previously defined. This is not seen in the original SQL query, maybe you missed it?
As I see it, the objective is to first obtain all the courses id that the Alumno_id
has assigned. Then, get all the courses that the Alumno_id
does not have assigned (by subtracting sets).
To put it in a more understandable way, what you want is: given a Alumno_id
corresponding to a Alumno
, get all the Cursos
that not are assigned to that student. If the goal you are pursuing not is the one I have described so far, leave a comment to know more precisely what you want to achieve.
The first instruction in the LINQ expression above can be rewritten as:
var cursosTomadosIds = (from cursoTomado in ctx.AlumnoCurso
where cursoTomado.Alumno_id == Alumno_id
select cursoTomado.Curso_id).ToList();
And the second instruction can be rewritten as:
var cursosNoTomados = (from curso in ctx.Curso
where !cursosTomadosIds.Contains(curso.id)).ToList();
You can combine both LINQ expressions with the help of the let
statement:
var cursosNoTomados = (from curso in ctx.Curso
let cursosTomadosIds = (from cursoTomado in ctx.AlumnoCurso
where cursoTomado.Alumno_id == Alumno_id
select cursoTomado.Curso_id).ToList()
where !cursosTomadosIds.Contains(curso.id)).ToList();
In this particular case, the combined expression is much less efficient than the expressions separately, since the expression let
is re-evaluated for each entry in the enumeration generated by the LINQ code. I recommend do not use the LINQ expression combined.
A left join
also works. You can define it as:
var query = from curso in ctx.Curso
join alumnoCurso in (from ac in ctx.AlumnoCurso
where ac.Alumno_id == ((Alumno_id))
select ac)
on curso.id equals alumnoCurso.Curso_id into g
where !g.Any()
select curso;
Note the presence of a sub-query that contains ((Alumno_id))
in the previous code. Alumno_id
(in double parentheses) must be a variable whose value is previously defined.
Any intrigue, do not hesitate to leave a comment!