在Nhibernate标准或Nhibernate Linq中加入查询

时间:2012-01-11 09:38:07

标签: nhibernate

我有一个我正在尝试运行的查询,但我没有得到理想的结果。

select * from employee_login e
left join employee_attendance ea on 
e.emp_id = ea.EmpId and dated = '2012-01-11'

我尝试使用Nhibernate的Linq查询是

 var attendance = from emp in session.Query<Employee>()
                                 join empatten in session.Query<EmployeeAttendance>()
                                 on emp.emp_id equals empatten.EmpId  into atts 
                                 from ur in atts.DefaultIfEmpty()                                     
                                 select new { ur };

在var出勤结果视图中。我怎样才能实现这两件事?

  1. 左边加入员工和员工出勤(员工是左表)
  2. a和条件在连接上而不是在连接结果上。
  3. 我使用Linq或分离标准对这种情况很新;一个独立的标准将是一个更好的答案。

    以下是模型:

    public class EmployeeAttendance
    {
        public virtual string No_ { get; set; }
        public virtual Employee Employee { get; set; }       
    }
    public class Employee
    {       
        public virtual string emp_id { get; set; }
        public virtual ISet<EmployeeAttendance> Attendances { get; set; }
        public Employee()
        {
            Attendances = new HashedSet<EmployeeAttendance>();
        } 
    }
    

    映射是:

    public class EmployeeAttendanceMap:ClassMap<EmployeeAttendance>
    {
        public EmployeeAttendanceMap()
        {
            Table("Employee_Attendance");
            Id(x => x.No_).GeneratedBy.Assigned();          
            References(x => x.Employee).Column("emp_id");
        }
    }
    public class EmployeeMap : ClassMap<Employee>
    {
        public EmployeeMap()
        {
            Table("employee_login");
            Id(x => x.emp_id).Column("emp_id").GeneratedBy.Assigned();           
    
            HasMany(x => x.Attendances).KeyColumn("No_").Cascade.All();        
        }
    }
    

    Employee是主表,AttendanceLeave的外键为Employee Table的EmpId

    编辑:我在上次尝试时也试过这个:

     ICriteria criteria = session.CreateCriteria(typeof(Employee), "emp")
                         .CreateAlias("EmployeeAttendance", "Attendance", CriteriaSpecification.LeftJoin
                         , Restrictions.Eq("Attendance.Dated", DateTime.Parse("2012-1-11")));
    

    但我最终得到错误:

      

    无法解析属性:EmployeeAttendance:Royal.Data.Core.Domain.Employee

1 个答案:

答案 0 :(得分:1)

看起来您希望员工在某个特定日期休假。我认为这样可行,但我之前从未使用过这种表达方式:

var detached = DetachedCriteria.For<AttendanceLeave>("al")
    .Add(Expression.Between('2012-01-11', "LeaveFrom", "LeaveTo"))  //this should be a DateTime
    .Add(Restrictions.EqProperty ("al.EmpId", "e.emp_id")) //make sure to use "e" for employee criteria alias
    .SetProjection (Projections.Count ("al.EmpId"));

var employeesOnLeave = session.CreateCriteria<Employee>("e")
    .Add(Restrictions.Gt(Projections.Subquery(detached), 0))
    .List();

您仍然可以获得每位员工的全套假期,但应该是您想要的员工。

更新 - 查看您的评论,看起来像这样的内容可能是您所追求的:

DateTime dateInQuestion = new DateTime(2012, 1, 11);

var employeesOnLeaveAsOfDateInQuestion =
                session.CreateCriteria<Employee>("e")
                    .CreateCriteria("e.Attendances", "ea"
                        , NHibernate.SqlCommand.JoinType.LeftOuterJoin
                        , Restrictions.Between(dateInQuestion, "ea.LeaveFrom", "ea.LeaveTo"))
                    .List<Employee>();

这似乎有效 - 但是你需要确保你得到的实体没有被缓存,否则将返回带有完整集合的缓存副本。 This是我测试过的 - 不完全像你的情况,因为收集是通过链接表维护的,但我认为它将以相同的方式工作 - 你可能需要专门用一个对一个来逐出系列虽然(在会话工厂中找到EvictCollection方法,而不是会话)。你应该只需要这个位进行测试(在我的测试中,数据库只在会话中存在)。如果您希望以这种方式解决问题,那么gist中还有一个QueryOver示例。