在net core 3.1中使用兩個表進行聯合查詢
// 內連接(lambda表達式又稱點標試)join方法的參數,第一個是要join的對象(下面是students),第二個是外部的(下面的teacher)key,第三個參數內部(下面是students)的key,第四個是結果(自己定義) var result = await _dbContext.teachers.Join(_dbContext.students, t => t.Id, s => s.TeacherId, (t, s) => new TeacherAndStudentDto { TeacherId = t.Id, TeacherName = t.Name, StudentId = s.Id, StudentName = s.Name }).ToListAsync();
// 內連接(linq表達式又稱查詢表達式) var result = await (from s in _dbContext.students join t in _dbContext.teachers on s.TeacherId equals t.Id select new TeacherAndStudentDto { TeacherId = t.Id, TeacherName = t.Name, StudentId = s.Id, StudentName = s.Name }).ToListAsync();
//左連接(已左表為基礎表(下面就是已students為基礎表),匹配條件,如果有就加上,沒有就已默認值添上)和sql中left join類似 var result = await (from s in _dbContext.students join t in _dbContext.teachers on s.TeacherId equals t.Id into newTeacher from nt in newTeacher.DefaultIfEmpty() //nt的類型為Teacher select new TeacherAndStudentDto { TeacherId = nt.Id, TeacherName = nt.Name, StudentId = s.Id, StudentName = s.Name }).ToListAsync();
最后我用groupjoin 先用下面的方法,可以查到數據
//左連接 var students = await _dbContext.students.ToListAsync(); var teachers = await _dbContext.teachers.ToListAsync(); var result = students.GroupJoin(teachers, s => s.TeacherId, t => t.Id, //調用的是 IEnumerable<TResult> GroupJoin<>這個方法,是已studens為基礎表,Teacher表附加到上面 (s, t) => new TeacherAndStudentDto // t為IEnumerable<Teacher> { StudentId = s.Id, StudentName = s.Name, TeacherId = s.TeacherId, TeacherName = t.FirstOrDefault(c => c.Id == s.TeacherId) == null ? null : t.FirstOrDefault(c => c.Id == s.TeacherId).Name } ).ToList();
然后我換一個方法
var result = await _dbContext.students.GroupJoin(_dbContext.teachers, s => s.TeacherId, t => t.Id, //調用IQueryable<TResult> GroupJoin<>這個方法 (s, t) => new TeacherAndStudentDto { StudentId = s.Id, StudentName = s.Name, TeacherId = t.FirstOrDefault(c => c.Id == s.TeacherId) == null ? 0 : t.FirstOrDefault(c => c.Id == s.TeacherId).Id, TeacherName = t.FirstOrDefault(c => c.Id == s.TeacherId) == null ? null : t.FirstOrDefault(c => c.Id == s.TeacherId).Name }).ToListAsync();
然后就報錯(暫時沒有找到問題所在)
An unhandled exception occurred while processing the request. InvalidOperationException: Processing of the LINQ expression 'DbSet<Student> .GroupJoin( outer: DbSet<Teacher>, inner: s => s.TeacherId, outerKeySelector: t => t.Id, innerKeySelector: (s, t) => new TeacherAndStudentDto{ StudentName = s.Name, TeacherName = t .FirstOrDefault(c => c.Id == s.TeacherId).Name } )' by 'NavigationExpandingExpressionVisitor' failed. This may indicate either a bug or a limitation in EF Core. See https://go.microsoft.com/fwlink/?linkid=2101433 for more detailed information. Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
8.3號更新(解決這個問題):看來還是要多看微軟EF文檔,大概的意思就是需要獲取所用的數據來進行groupjoin,這也就是IEnumerable可以調用,而IQuerable這個不可用的原因,具體看下面鏈接
https://docs.microsoft.com/zh-cn/ef/core/querying/complex-query-operators
一些相關的類
public class TeacherAndStudentDto { public int TeacherId { get; set; } public string TeacherName { get; set; } public string StudentName { get; set; } public int StudentId { get; set; } } public class Teacher { [Key] public int Id { get; set; } public string Name { get; set; } /// <summary> /// 所教科目 /// </summary> public string Subject { get; set; } public GenderEnum GenderEnum { get; set; } public DateTime Birthday { get; set; } public double Hegiht { get; set; } public double? Weight { get; set; } } public class Student { [Key] public int Id { get; set; } public string Name { get; set; } public DateTime? Birthday { get; set; } /// <summary> /// 學號 /// </summary> public string Numerber { get; set; } /// <summary> /// 分數 /// </summary> public int? Score { get; set; } /// <summary> /// 年級 /// </summary> public string Grade { get; set; } public GenderEnum? GenderEnum { get; set; } public double Hegiht { get; set; } public double? Weight { get; set; } public int TeacherId { get; set; } } public enum GenderEnum { [Description("女")] Female=0, [Description("男")] Male =1, } public class EFCoreDbContext : DbContext { public EFCoreDbContext(DbContextOptions<EFCoreDbContext> options) : base(options) { } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { //如果appseting.json中沒有配置數據庫連接,會讀取這里的配置 if (!optionsBuilder.IsConfigured) { optionsBuilder.UseSqlServer("Server=.;Data Source=(local);uid=sa;pwd=xxx;DataBase=xxx"); } base.OnConfiguring(optionsBuilder); } protected override void OnModelCreating(ModelBuilder modelBuilder) { //Fluent API } public DbSet<Teacher> teachers { get; set; } public DbSet<Student> students { get; set; } }
這個問題還要摸索一下(已解決),以后解決吧,又要學習go語言了
https://www.cnblogs.com/zitjubiz/p/a-left-outer-join-using-linq-extension-methods.html