2015-04-15 5 views
0

мне нужно сделать это SQL в ORMLite Sql Server: (Если я прохожу 0 в параметрах, то я удалить фильтр, как и в SQL:ServiceStack ORMLite Sql Server * дополнительный фильтр

declare @departmentId int = 0; 
declare @projectTaskStatusId int = 0; 
select * from ProjectTask t 
join Project p on p.ProjectId = t.ProjectId  
where 
(p.DepartmentId = @departmentId or @departmentId = 0) and 
(t.ProjectTaskStatusId = @projectTaskStatusId or @projectTaskStatusId = 0) 

Я создал этот код ниже, но это не работает, что это лучший способ сделать это, где в ORMLite SQL Server?

dbCon.LoadSelectAsync(x => (x.Project.DepartmentId == departmentId || departmentId == 0) && (x.ProjectTaskStatusId == projectTaskStatusId || projectTaskStatusId == 0));

Я мог заставить его работать, используя код ниже (но это с помощью лямбда и не прямо OrmLite:

var tasks = await dbCon.LoadSelectAsync<ProjectTask>(x => x); 
return tasks.Where(x => (departmentId == 0 || x.Project.DepartmentId.Equals(departmentId)) && (projectTaskStatusId == 0 || x.ProjectTaskStatusId.Equals(projectTaskStatusId))); 

После помощи вас, ребята, я мог бы сделать решение ниже, однако, я думаю, что это дорого, потому что я не могу использовать LoadReferences только SelectAsync, а затем мне нужно сделать foreach, чтобы вручную загружать каждую ссылку :

var query = dbCon.From<ProjectTask>() 
        .Join<ProjectTask, Project>((pt, p) => pt.ProjectId == p.Id) 
        .Where<Project>(p => p.DepartmentId == departmentId || departmentId == 0) 
        .And<ProjectTask>(pt => pt.ProjectTaskStatusId == projectTaskStatusId || projectTaskStatusId == 0); 

var tasks = await dbCon.SelectAsync(query); 

// Load the references 
foreach (var item in tasks) 
{ 
    if (item.ProjectId > 0) 
     item.Project = await dbCon.SingleByIdAsync<Project>(item.ProjectId); 

    if (item.AssignedToId > 0) 
     item.AssignedTo = await dbCon.SingleByIdAsync<Employee>(item.AssignedToId); 

    if (item.RequestedById > 0) 
     item.RequestedBy = await dbCon.SingleByIdAsync<Employee>(item.RequestedById); 

    if (item.ProjectTaskStatusId > 0) 
     item.ProjectTaskStatus = await dbCon.SingleByIdAsync<ProjectTaskStatus>(item.ProjectTaskStatusId); 
} 

return tasks; 

ответ

1

у меня нет кода передо мной прямо сейчас, так что я мог бы быть покинуть базу немного по синтаксису, но я думаю, что следующий код будет трансформироваться в эквивалентный запрос.

var query = db.From<ProjectTask>() 
       .Join<ProjectTask, Project>((pt, p) => pt.ProjectId == p.ProjectId) 
       .Where<Project>(p => p.DepartmentId == departmentId || departmentId == 0) 
       .And<ProjectTask>(pt => pt.ProjectTaskStatusId == statusId || statusId == 0); 

var tasks = await dbCon.SelectAsync<ProjectTask>(query); 

Отказ от ответственности: Это для Servicestack.OrmLite версии 4.0 + с его новыми изящными классов SqlExpression.

Update:

Хорошо, я вижу, что вы пытаетесь сделать сейчас.
Да, загрузка ссылок в цикле for как это не очень эффективное решение. Я не уверен, почему методы LoadSelect не работают (вы можете сообщить об этом как возможную ошибку, если у вас есть хороший тест для воспроизведения), но для этого может быть обходной путь.

Если вы копаете исходный код OrmLite и проверяете, что на самом деле вы видите, что то, что на самом деле делается под обложками LoadSelect, заключается в том, что запрос выполняется первым, а затем OrmLite выполняет итерацию по определению модели и проблемам запрос вида

SELECT columns FROM table WHERE id IN (originalquery)

для каждой из ссылок. Затем он принимает результат этого запроса и подключает результаты к ссылкам. Таким образом, OrmLite фактически выдает несколько запросов при использовании LoadSelect, хотя это будет 1 запрос на ссылку вместо 1 запроса на ссылку на объект, что намного лучше.

Вы можете сделать эту стратегию вручную. Хотя это будет немного хлопот ... Я не даю вам никакого кода для этого прямо сейчас, так как у меня нет компьютера с VS передо мной прямо сейчас, и это немного более продвинуто, поэтому я не Думаю, я смогу догадаться об этом.

Однако вам действительно нужны все эти ссылки? Я просто догадываюсь, но это похоже на множество данных, которые вы загружаете за один раз. Вам действительно нужны все эти ссылки и столбцы, или вам просто нужно несколько из них? Если вам действительно действительно нужно несколько из них, вы можете пойти с объединением в пользовательскую модель, используя только те столбцы, которые вам действительно нужны. Это будет самый эффективный вариант, поскольку вы сможете сделать это в одном запросе и только перенести данные, которые вам действительно нужны, а не все. Но я не знаю, как вы используете эти данные, чтобы это не было хорошим вариантом. :)

Но, как сказано, возможно, вы обнаружили ошибку в LoadSelect!Я настоятельно рекомендую вам добавить его в систему отслеживания проблем и посмотреть, исправит ли он это - по моему опыту ServiceStack очень быстро реагирует и исправляет ошибки. Особенно, если вы дадите им воспроизводимый модульный тест (который вы, вероятно, можете извлечь из своего кода довольно легко).

https://github.com/ServiceStack/Issues/issues

+0

Это сработало! Однако только при использовании: SelectAsync, если я использую: LoadSelectAsync, у меня есть ошибка: Код ошибки SqlException Сообщение Неоднозначное название столбца 'ProjectId'. –

+0

LoadSelectAsync может автоматически загружать все мои ссылки, поэтому я бы хотел использовать его, чтобы не загружать после каждой ссылки с помощью команды: LoadReference –

+0

Я отправил новую проблему в ServiceStack github, спасибо! –