ServiceStack ORMLite Sql Server *可选过滤器

时间:2015-04-15 01:38:11

标签: c# sql-server ormlite ormlite-servicestack

我需要在ORMLite Sql Server中执行此SQL :(如果我在参数中传递0,那么我将删除过滤器,如SQL中所示:

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

我可以使用下面的代码使其工作(但这是使用Lambda而不是直接在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)));

在你们的帮助下,我可以在下面做解决方案,但是,我认为这是昂贵的,因为我不能仅使用SelectReync的LoadReferences,然后我必须做一个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 个答案:

答案 0 :(得分: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类。

更新

好的,我知道你现在要做的是什么 是的,在这样的for循环中加载引用不是非常有效的解决方案。我不确定为什么LoadSelect方法不起作用(如果你有一个很好的复制测试,你可能想报告这个可能的错误),但可能有一个解决方法。

如果你深入研究OrmLite源代码并检查它实际上做了什么,你可以看到在LoadSelect的封面下实际完成的是查询首先运行然后OrmLite迭代模型定义并发出表格的查询

SELECT columns FROM table WHERE id IN (originalquery)

每个参考文献。然后它获取该查询的结果并将结果连接到引用。因此,当使用LoadSelect时,OrmLite实际上会在这里发出几个查询,尽管每个引用将是1个查询,而不是每个对象每个引用1个查询,这要好得多。

您可以手动执行此策略。虽然这会有点麻烦......我现在没有给你任何代码,因为我现在没有在我面前有VS的电脑,而且这有点先进,所以我不喜欢我想我能猜到这一点。

但是,你真的需要所有这些参考吗?我现在只是在猜测,但这看起来像是你要一次加载的大量数据。你真的需要所有这些参考和专栏吗?或者你只需​​要几个?如果您只需要其中的几个,那么您可能希望将连接添加到自定义模型中,而只使用您实际需要的列。这将是性能最高的选项,因为您可以在一个查询中执行此操作,并且只传输您实际需要的数据而不是所有内容。但我不知道你是如何使用这些数据的,所以这可能不是一个好的选择。 :)

但如上所述,您可能在LoadSelect中发现了一个错误!我强烈建议你将它添加到问题跟踪器,看看他们是否会修复它 - 根据我的经验,ServiceStack在响应和修复错误方面非常快。特别是如果你给它们一个可重复的单元测试(你很可能很容易从你的代码中提取)。

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