linq和lambda表達式,已經使用join和groupjoin


在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

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM