AutoQuery: объединять таблицы через промежуточную таблицу и определять, к какому FK присоединяться
Мы начали использовать ServiceStack AutoQuery недавно. Это хорошая особенность, и нам действительно понравилось. У нас есть такая структура таблицы (сокращенная версия, чтобы ее было легко читать):
Salary [Id (PK), ManagerId (FK)]
Manager [Id (PK), DepartmentId (FK)] /* Manager is like Employee table even thought it's named Manager */
Department [Id (PK), ActiveManagerId (FK)] /* The FK ActiveManagerId is supposed to be a shortcut, it's Nullable. */
Так что теоретически мы можем иметь соединения как
Salary -> Manager via Salary.ManagerId = Manager.Id
Manager -> Department via Manager.DepartmentId = Department.Id
Department -> Manager via Department.ActiveManagerId = Manager.Id
Однако в этом конкретном случае, если мы присоединяемся от Department к Manager через Department.ActiveManagerId = Manager.Id, мы не получим правильных результатов, потому что Department.ActiveManagerId является ярлыком и предназначен для других сценариев.
Поэтому, когда я определяю AutoQuery следующим образом
public class SalaryQuery : QueryBase<Salary, SalaryQueryResult>,
ILeftJoin<Salary, Manager, Department>
Ниже SQL производится AutoQuery, что является правильным с точки зрения ServiceStack AutoQuery.
select s.Id
, d.Id
from Salary s
left join
Manager m
on s.ManagerId = m.Id
left join
Department d
on d.ActiveManagerId = m.Id /* should NOT use shortcut: Department -> Manager via Department.ActiveManagerId = Manager.Id */
Но вместо этого мы хотим иметь возможность производить SQL, который выглядит следующим образом
select s.Id
, d.Id
from Salary s
left join
Manager m
on s.ManagerId = m.id
left join
Department d
on d.Id = m.DepartmentId /* should use the desired FK: Manager -> Department via Manager.DepartmentId = Department.Id */
1 ответ
Если вам нужно другое поведение JOIN, вам нужно добавить пользовательское LEFT JOIN в реализацию Custom AutoQuery, например:
//AutoQuery DTO
public class SalaryQuery : QueryDb<Salary,SalaryQueryResult>, ILeftJoin<Salary,Manager>
//Implementation
public class MyServices : Service
{
public IAutoQueryDb AutoQuery { get; set; }
public object Any(SalaryQuery query)
{
var q = AutoQuery.CreateQuery(query, base.Request)
.LeftJoin<Manager, Department>((m, d) => d.Id == m.DepartmentId);
return AutoQuery.Execute(query, q);
}
}
Примечание: от v4.0.56
QueryBase<T>
устарела и переименована в QueryDb.