0

I'm attempting to accomplish paging in my ServiceStack (4.0.50) services, and I'm running into an issue when the query has multiple joins using LoadSelect.

In order to filter results for security requirements, my Get method pulls info from a custom user session and builds a query. Something like this:

public QueryResponse<Foo> Get(Foos request)
{
    var session = SessionAs<CustomUserSession>();

    var q = Db.From<Foo>().LeftJoin<Foo, User>((s, u) => s.UserId == u.Id);

    // Also tried this with no success
    //q.Skip(request.Skip);
    //q.Take(request.Take);
    q.Limit(request.Skip, request.Take);

    // I do filtering based on the request object for searching
    if (request.Price.HasValue)
    {
        q.And(s => s.Price == request.Price);
    }
    // ... and so on ...

    // Then I do filtering based on roles
    if (session.HasRole("OrgAdmin"))
    {
        // Do some filtering for their organization
    }
    else if (session.HasRole("SiteManager"))
    {
        // More filtering here
    }

    // Ordering also...
    if (request.OrderBy.IsNullOrEmpty())
    {
        q.OrderByFieldsDescending(request.OrderByDesc);
    }
    else
    {
        q.OrderByFields(request.OrderBy);
    }

    var response = new QueryResponse<Foo>
    {
        // This works fine
        Total = (int)Db.Count(q),
        // === Error here ===
        Results = Db.LoadSelect(q)
    };

    return response;
}

The count always works fine, and the first page of results always works. However, pulling subsequent pages of results gets the following error: Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.

Unfortunately, I need to apply the filtering, which requires the joins. Unfortunately I need to load the references and want to avoid a select n+1 situation. I've tried inspecting the SQL expressions in the q object, but it doesn't look like there's any way to see what the true final SQL is that's sent to the server.

Any suggestions?

NOTE: I'm not using AutoQuery, I just appropriated the QueryBase<> and QueryResponse<> objects to use the paging and count properties.

Josh Anderson
  • 5,975
  • 2
  • 35
  • 48
  • Have a look at [this question](http://stackoverflow.com/questions/1904314/only-one-expression-can-be-specified-in-the-select-list-when-the-subquery-is-not). It may be that a subquery has more than one column in it. You really need to know what SQL is being generated. – Quantumplate Dec 19 '15 at 19:25
  • Unfortunately I don't think that's possible, unless I use the ServiceStack source and try to debug it, which I'd rather not do. – Josh Anderson Dec 19 '15 at 20:23
  • There is usually a way! Can you use something like wireshark to inspect packets? http://internationaldatascience.com/using-wireshark-to-viewtrack-sql-server-browser-traffic/ or maybe some logging in SQL Server? I'm sorry I'm not familiar with ServiceStack so don't know how that works. – Quantumplate Dec 19 '15 at 20:29

1 Answers1

2

As it turns out this is a problem with the standard SqlServerDialect.Provider. Since this is SQL 2012, when I switched to SqlServer2012Dialect.Provider in the AppHost it worked as expected.

Josh Anderson
  • 5,975
  • 2
  • 35
  • 48
  • By the way, you can know the SQL generated using Db.GetLastSql() (place a try... catch block and call Db.GetLastSql() inside the catch). – labilbe Dec 21 '15 at 11:22
  • The problem is due to the fact SQL generated before SQL Server 2012 cannot use the LIMIT statement which facilitate SQL generation. Until SQL Server 2008 one must use a complex SQL syntax to do the job. – labilbe Dec 21 '15 at 11:24