1

次の状況でクエリを作成しようとすると、非常に困難になります。

私のコア フレームワーク (コードではないため変更できません) には、次の 2 つのクラスがあります。

[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;}
}

今私が欲しいのは、すべての生徒と教師の最後のテストレポートを取得するためのクエリですが、教師または生徒がテストを受けていない場合でも、概要に表示されるはずです。そこで、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>();
}

誰かが私を正しい方向に向けることができますか?学生と教師のクラスにマッピングを追加できないことを覚えておいてください

4

1 に答える 1

1

選択をまとめてバッチ処理する Future という便利な機能があります。以下を考えると

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; }
}

クエリは次のようになります

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);
于 2012-08-14T09:08:29.083 に答える