加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 显式加载N:M过滤[复制]

发布时间:2020-12-15 08:06:30 所属栏目:百科 来源:网络整理
导读:参见英文答案 How to manually load related entities in a N:N relationship?2个 我试图从EntityFramework中的显式加载过滤结果. 当我不应用任何过滤器但是在应用过滤器后它不加载结果时,显式加载有效. 类 public partial class Student{ public int Studen
参见英文答案 > How to manually load related entities in a N:N relationship?2个
我试图从EntityFramework中的显式加载过滤结果.

当我不应用任何过滤器但是在应用过滤器后它不加载结果时,显式加载有效.

public partial class Student
{
    public int StudentId { get; set; }
    public int CourseId { get; set; }
    public string Name { get; set; }
    public string Status { get; set; }
    public virtual ICollection<Grade> Grades { get; set; }
}

public partial class Grade
{
    public int GradeId { get; set; }
    public string Value { get; set; }
    public string Status { get; set; }
    public virtual ICollection<Student> Students { get; set; }
}

流畅的API映射

modelBuilder.Entity<Grade>()
    .HasMany(e => e.Students)
    .WithMany(x => x.Grades)
    .Map(m => m.ToTable("StudentGrades").MapLeftKey("GradeId").MapRightKey("StudentId"));

用法

这适用于学生.Grades属性.

using (var context = new Model1())
{
    context.Configuration.LazyLoadingEnabled = false;

    var student = context.Students.Single(x => x.StudentId == 1);
    context.Entry(student).Collection(x => x.Grades).Load();
}

生成的SQL如下所示:

SELECT 
[Extent2].[GradeId] AS [GradeId],[Extent2].[Value] AS [Value],[Extent2].[Status] AS [Status]
FROM  [dbo].[StudentGrades] AS [Extent1]
INNER JOIN [dbo].[Grades] AS [Extent2] ON [Extent1].[GradeId] = [Extent2].[GradeId]
WHERE [Extent1].[StudentId] = 1 // this is parameterized in the actual hit.

当我运行此查询时,我得到了完整的结果.

但是,当我应用过滤并使用以下行时,它不会填充student.Grades.

context.Entry(student).Collection(x => x.Grades).Query().Where(x => x.Status == "A").Load();

此行生成此查询:

SELECT 
[Extent2].[GradeId] AS [GradeId],[Extent2].[Status] AS [Status]
FROM  [dbo].[StudentGrades] AS [Extent1]
INNER JOIN [dbo].[Grades] AS [Extent2] ON [Extent1].[GradeId] = [Extent2].[GradeId]
WHERE ([Extent1].[StudentId] = 1) AND ('A' = [Extent2].[Status])
//the "1" is parameterized in the actual hit.

当我手动对数据库运行时,我在SQL Server中获得正确筛选的结果.问题是这不会填充C#对象中的student.Grades.

解决方法

在明确加载相关实体部分时,MSDN Article – 应用过滤器中提到了这种技术,因此它应该得到支持和工作.奇怪的是,它适用于一对多关系,多对多具有显式链接表和2个一对多关联,但不适用于具有隐式链接表的多对多关系.

我没有解释为什么(没有找到相关文档).我也没有解释为什么,但将它与急切加载其他集合的请求相结合可以解决问题:

context.Entry(student).Collection(s => s.Grades)
    .Query().Where(g => g.Status == "A")
    .Include(g => g.Students)
    .Load();

这个的缺点(如评论中所提到的)是它还会加载很多属于加载等级的学生.

所以更好的方法是使用显式链接表和这样的关系:

模型:

public partial class Student
{
    public int StudentId { get; set; }
    public int CourseId { get; set; }
    public string Name { get; set; }
    public string Status { get; set; }
    public virtual ICollection<StudentGrade> StudentGrades { get; set; }
}

public partial class Grade
{
    public int GradeId { get; set; }
    public string Value { get; set; }
    public string Status { get; set; }
    public virtual ICollection<StudentGrade> StudentGrades { get; set; }
}

public class StudentGrade
{
    public int StudentId { get; set; }
    public int GradeId { get; set; }
    public virtual Student Student { get; set; }
    public virtual Grade Grade { get; set; }
}

组态:

modelBuilder.Entity<StudentGrade>()
   .ToTable("StudentGrades")
   .HasKey(e => new { e.GradeId,e.StudentId });

modelBuilder.Entity<StudentGrade>()
    .HasRequired(e => e.Grade)
    .WithMany(x => x.StudentGrades)
    .HasForeignKey(e => e.GradeId)
    .WillCascadeOnDelete();

modelBuilder.Entity<StudentGrade>()
    .HasRequired(e => e.Student)
    .WithMany(x => x.StudentGrades)
    .HasForeignKey(e => e.StudentId)
    .WillCascadeOnDelete();

现在显式加载不需要技巧,并且将加载已填充的GradeId和StudentId字段的已过滤的相关StudentGrade实体,从而避免加载其他Grade和Student对象:

context.Entry(student).Collection(s => s.StudentGrades)
    .Query().Where(sg => sg.Grade.Status == "A")
    .Load();

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读