2012-08-08 90 views
1

我在嘗試寫以下情況的查詢巨大的困難:NHibernate的子查詢

在我的核心框架(至極我不能修改,因爲這不是我們的代碼)我有兩個類:

[Class(Table = "Teacher")] 
public class Teacher 
{ 
    [Id] 
    public virtual long? Id {get;set;} 

    [Property] 
    public virtual string EmployeeNr{get;set;} 
} 

[Class(Table = "Student")] 
public class Student 
{ 
    [Id] 
    public virtual long? Id{get;set;} 

    [Property] 
    public virtual string Name{get;set;} 
} 

接下來,在我的應用程序層我已經建立了下面的類來記錄學生和教師做測試

[Class(Table = "TestReports", DiscriminatorValueObject = 1)] 
public class TestReport 
{ 
    [Id] 
    public virtual long? Id{get;set;} 

    [Property] 
    public virtual string TestName{get;set;} 

    [Property] 
    public virtual DateTime Date{get;set;} 

    [Property] 
    public virtual int Correct{get;set;} 

    [Property] 
    public virtual int InCorrect{get;set;} 

    [Property] 
    public virtual int Unanswerd{get;set;} 

} 

[Subclass(NameType = typeof(StudentTestReport), ExtendsType = typeof(TestReport), DiscriminatorValueObject = 2)] 
public class StudentTestReport 
{ 
    [ManyToOne] 
    public virtual Student Student{get;set;} 
} 

[Subclass(NameType = typeof(TeacherTestReport), ExtendsType = typeof(TestReport), DiscriminatorValueObject = 3)] 
public class TeacherTestReport 
{ 
    [ManyToOne] 
    public virtual Teacher Teacher{get;set;} 
} 

現在的信息我想是一個查詢來獲取最後testreportØ f所有學生和老師但是如果老師或學生沒有進行任何測試,他們仍應該在概覽中顯示。所以我決定採取AliasToBeanTranformer方法和創建報表的包裝對象:

public class TestOverviewWrapper 
{ 
    public virtual string TestName{get;set;} 
    public virtual DateTime Date{get;set;} 
    public virtual int Correct{get;set;} 
    public virtual int InCorrect{get;set;} 
    public virtual int Unanswerd{get;set;} 
    public virtual long Id{get;set;} 
    public virtual string Name{get;set;} 
    public virtual string EmployeeNr{get;set;} 

    public virtual string Person 
    { 
      get{ return Name ?? EmployeeNr;} 
    } 
} 

我有巨大的麻煩越來越查詢權,我想看看我是否能得到的只是學生和他們的最後一次測試報告,但我卡住投影到包裝對象的子查詢的屬性。這是我在多大程度上得到:

public IList<TestOverviewWrapper> GetTestOverview() 
{ 
    var crit = SessionFactory.GetCurrentSession().CreateCriteria<Student>("st"); 

    var dcrit = DetachedCriteria.For<StudentTestReport>("lastTest") 
     .Add(Subqueries.PropertyEq("Date", 
            DetachedCriteria.For<StudentTestReport>("test") 
             .Add(Restrictions.EqProperty("lastTest.Student", "st.Id")) 
             .SetProjection(Projections.Max("lastTest.Date")))); 

    dcrit.Add(Restrictions.EqProperty("lastTest.Student", "st.Id")); 

    crit.Add(Subqueries.Select(dcrit)); 

    crit.SetProjection(Projections.ProjectionList() 
          .Add(Projections.Property("lastTest.Id") 
          .Add(Projections.Property("lastTest.TestName") 
          .Add(Projections.Property("lastTest.Date") 
          .Add(Projections.Property("lastTest.Correct") 
          .Add(Projections.Property("lastTest.Incorrect") 
          .Add(Projections.Property("lastTest.Unanswerd") 
          .Add(Projections.Property("st.Id") 
          .Add(Projections.Property("st.Name") 
         ); 

    crit.SetResultTransformer(Transformers.AliasToBean<TestOverview>()); 
    return crit.List<TestOverviewWrapper>(); 
} 

任何人都可以點我在正確的方向,記得我不能對學生和教師類添加映射

回答

1

有一個叫未來批量一個方便的功能一起選擇。考慮到如下因素

public class TestOverviewWrapper 
{ 
    public virtual string TestName { get; set; } 
    public virtual DateTime Date { get; set; } 
    public virtual int Correct { get; set; } 
    public virtual int InCorrect { get; set; } 
    public virtual int Unanswerd { get; set; } 
    public virtual long Id { get; set; } 
    public virtual string Person { get; set; } 
} 

查詢(IES)看起來像

var studentTests = session.CreateCriteria<StudentTestReport>("test") 
    .Add(Subqueries.PropertyEq("Date", DetachedCriteria.For<StudentTestReport>() 
     .Add(Restrictions.EqProperty("Student", "test.Student")) 
     .SetProjection(Projections.Max("lastTest.Date")))) 
    .CreateAlias("Student", "student") 
    .SetProjection(Projections.ProjectionList() 
     .Add(Projections.Property("TestName"), "TestName") 
     .Add(Projections.Property("Date"), "Date") 
     .Add(Projections.Property("Correct"), "Correct") 
     .Add(Projections.Property("Incorrect"), "Incorrect") 
     .Add(Projections.Property("Unanswerd"), "Unanswerd") 
     .Add(Projections.Property("student.Id"), "Id") 
     .Add(Projections.Property("student.Name"), "Person")) 
    .SetResultTransformer(Transformers.AliasToBean<TestOverviewWrapper>()) 
    .Future<TestOverviewWrapper>(); 

var studentsWithoutTests = session.CreateCriteria<Student>("student") 
    .Add(Subqueries.NotExists(DetachedCriteria.For<StudentTestReport>() 
     .Add(Restrictions.EqProperty("Student", "student")))) 
    .SetProjection(Projections.ProjectionList() 
     .Add(Projections.Property("Id"), "Id") 
     .Add(Projections.Property("Name"), "Person")) 
    .SetResultTransformer(Transformers.AliasToBean<TestOverviewWrapper>()) 
    .Future<TestOverviewWrapper>(); 

var teacherTests = session.CreateCriteria<TeacherTestReport>("test") 
    .Add(Subqueries.PropertyEq("Date", DetachedCriteria.For<TeacherTestReport>() 
     .Add(Restrictions.EqProperty("Teacher", "test.Teacher")) 
     .SetProjection(Projections.Max("lastTest.Date")))) 
    .CreateAlias("Teacher", "teacher") 
    .SetProjection(Projections.ProjectionList() 
     .Add(Projections.Property("TestName"), "TestName") 
     .Add(Projections.Property("Date"), "Date") 
     .Add(Projections.Property("Correct"), "Correct") 
     .Add(Projections.Property("Incorrect"), "Incorrect") 
     .Add(Projections.Property("Unanswerd"), "Unanswerd") 
     .Add(Projections.Property("teacher.Id"), "Id") 
     .Add(Projections.Property("teacher.EmployeeNr"), "Person")) 
    .SetResultTransformer(Transformers.AliasToBean<TestOverviewWrapper>()) 
    .Future<TestOverviewWrapper>(); 

var teacherWithoutTests = session.CreateCriteria<Teacher>("teacher") 
    .Add(Subqueries.NotExists(DetachedCriteria.For<TeacherTestReport>() 
     .Add(Restrictions.EqProperty("Teacher", "teacher")))) 
    .SetProjection(Projections.ProjectionList() 
     .Add(Projections.Property("Id"), "Id") 
     .Add(Projections.Property("EmployeeNr"), "Person")) 
    .SetResultTransformer(Transformers.AliasToBean<TestOverviewWrapper>()) 
    .Future<TestOverviewWrapper>(); 

return studentTests.Concat(studentsWithoutTests).Concat(teacherTests).Concat(teacherWithoutTests);