Ho sotto le entità e la classe di contesto del database,
public class Grade
{
public int Id { get; set; }
public string GradeName { get; set; }
public virtual ICollection<Student> Students { get; set; } = new HashSet<Student>();
}
public class Student
{
public int Id { get; set; }
public string StudentName { get; set; }
}
public class SchoolContext : DbContext
{
public DbSet<Grade> Grades { get; set; }
public DbSet<Student> Students { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Server=(localdb)\MSSQLLocalDB;Database=SchoolDB;Trusted_Connection=True;");
}
}
Ottenere sotto l'errore durante l'esecuzione sotto il codice, che cosa deve essere fatto qui. Grazie!
Sto cercando una soluzione senza aggiungere la proprietà Grade nella classe Student
System.InvalidOperationException: 'L'espressione lambda della proprietà Include' x => {dallo Studente c in x.Students dove [[c] .Id == __studentId_0) seleziona [c]} 'non è valido. L'espressione dovrebbe rappresentare un accesso alla proprietà: 't => t.MyProperty'. Per targetizzare le navigazioni dichiarate sui tipi derivati, specificare un parametro lambda tipizzato in modo esplicito del tipo di destinazione, ad es. '(Derivato d) => d.MyProperty'. Per ulteriori informazioni sull'inclusione dei dati correlati, vedere http://go.microsoft.com/fwlink/?LinkID=746393 . "
static void Main(string[] args)
{
var studentId = 1;
var context = new SchoolContext();
var data = context.Grades.Include(x => x.Students.Where(c => c.Id == studentId)).SingleOrDefault();
}
Sto cercando una soluzione senza aggiungere la proprietà Grade nella classe Student
Quindi vuoi essere in grado di ottenere il Grade
per uno Student
, ma non vuoi aggiungere la proprietà di navigazione di Grade
a Student
e lasciare che l'EF Core gestisca naturalmente questo per te? In altre parole, perdere uno dei maggiori vantaggi di ORM e iniziare a cercare soluzioni SQL-ish per una semplice richiesta che ORM può gestire con una semplice proprietà accessor?
Ci sono modi per fare ciò che vuoi, ma ti suggerirei prima chiedendoti se ne hai davvero bisogno.
Ad ogni modo, una possibile soluzione consiste nell'utilizzare la proprietà di navigazione della raccolta con il filtro Any
come:
var studentGrade = context.Grades
.FirstOrDefault(grade => grade.Students.Any(student => student.Id == studentId));
Un altro è usare l'equivalente LINQ della query SQL:
var studentGrade = (
from grade in context.Grades
from student in grade.Students
where student.Id == studentId
select grade).FirstOrDefault();
Non è possibile includere la proprietà di navigazione in base alle condizioni. Includi può contenere solo lambda alla proprietà di navigazione senza alcuna condizione. Per risolvere il tuo problema devi aggiungere la proprietà di navigazione di livello in classe Studente e selezionare tra gli Studenti, incluso Grado.
public class Student
{
public int Id { get; set; }
public string StudentName { get; set; }
public Grade StudentGrade { get; set; }
}
…
var data = context.Students.Include(x => x.Grade).Where(c => c.Id == studentId).SingleOrDefault();