2012-01-11 3 views
0

У меня есть запрос, который я пытаюсь запустить, но я не получаю желаемого результата.Присоединиться к запросу в критериях Nhibernate или в Nhibernate Linq

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

Запрос Linq, который я пытался с NHibernate является

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

В посещаемости вар resultview. Как я могу достичь этих двух вещей?

  1. левый присоединиться к более сотрудника и employeeattendance (работник левая таблица)
  2. а и условие на объединение не над присоединиться к результату.

Я довольно новичок в этой ситуации с использованием 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();   
    } 
} 

Работник является основной таблицей и AttendanceLeave имеет внешний ключ, как EmpId из таблицы Employee

Edit: Я попробовал это также в своей последней попытке:

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

+0

'select * from employee_login e left join employee_attendance ea on e.emp_id = ea.EmpId и ea.датированные = '2012-01-11'' должно быть эквивалентно 'выбрать * из employee_login е осталось присоединиться employee_attendance еа на e.emp_id = ea.EmpId где ea.dated =' 2012-01-11 «'. Существует ли какая-либо Ассоциация между классом Employee и EmployeeAttendance в вашей модели? – Firo

+0

@Firo жаль, что я забыл поставить домены. да, есть ассоциация между Employee Class и EmployeeAttendance в модели, где EmpId является внешним ключом – Joy

ответ

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 метод найден на фабрике сеанса, а не на сеансе). Этот бит нужно использовать только для тестирования (в моих тестах база данных работает только до тех пор, пока сессия). Существует также пример QueryOver в gist, если вы предпочитаете его решать таким образом.

+0

, у вас есть сценарий совсем немного. Дело в том, что я хочу, чтобы все сотрудники, поэтому я делаю левые, присоединяюсь от сотрудников к сотрудникам и получаю их статус. даже если в правой таблице нет присутствия, в этом случае он вернет сотрудников на определенную дату, но если в эту конкретную дату не будет присутствовать, тогда он должен вернуть значение null в поля посещаемости. – Joy

+0

http://stackoverflow.com/questions/2756148/nhibernate-left-outer-join Эта ссылка - точное совпадение, которое я хочу сделать. Он дал решение, но я не понимаю, как заставить его работать. Я имею в виду, как его выполнить. не могли бы вы помочь мне? – Joy

+0

Проверьте обновление, которое я только что разместил, я думаю, что он будет делать то, что вы хотите - просто следите за упомянутыми проблемами кеша. – AlexCuse

Смежные вопросы