ServiceStack Ormlite using Select with NoLock - servicestack

I have the following simple OrmLite select statement:
SpiderUser lSpiderUser = db.Select<SpiderUser>(
su => su.WindowsUserName == vWindowsUserName).SingleOrDefault();
(The variable 'db' is of type IDbConnection).
I would like this query to run using NoLock. Ormlite from version 5.7 has 'SqlServerTableHint.NoLock', but I do not understand how to include this hint in the above query.
Please help...

OrmLite's SqlServerTableHint are only for table joins.
You can customize the generated SQL using a Typed SqlExpression, e.g:
var q = db.From<SpiderUser>()
.Where(su => su.WindowsUserName == vWindowsUserName)
.WithSqlFilter(sql => $"{sql} WITH (NOLOCK)");
var lSpiderUser = db.Single(q);

Related

Use SELECT DISTINCT ON with OrmLite

I tried writing this code to use SELECT DISTINCT ON:
var q = Db.From<WatchedUrlScanResult>();
q.Join<WatchedUrlRecord>()
.Where<WatchedUrlRecord>(x => x.TargetDomainRecordId == request.TargetDomainId)
.And(x => x.ScanDate < fromEnd)
.OrderBy(x => x.WatchedUrlRecordId)
.OrderByDescending(x => x.ScanDate);
q.SelectExpression = q.SelectExpression.Replace("SELECT",
$"SELECT DISTINCT ON ({q.Column<WatchedUrlScanResult>(x => x.WatchedUrlRecordId)})");
var fromSnapshot = Db.Select<WatchedUrlScanResult>(q);
In debugger it shows the value has set for SelectExpression but the actual SQL that runs is just SELECT without DISTINCT ON.
I tried:
q.Select(q.SelectExpression.Replace("SELECT",
$"SELECT DISTINCT ON ({q.Column<WatchedUrlScanResult>(x => x.WatchedUrlRecordId)})"));
But I get:
Potential illegal fragment detected
Is it possible to do this without making full query a string? (using {q.Column<Table>(x => x.ColumnName)} in a full string query is fine but not very readable compared to fluent syntax)
If you want to perform a SELECT DISTINCT query in OrmLite using its SqlExpression<T> you would use the SelectDistinct() API, e.g:
var results = Db.Select(q.SelectDistinct());
But as you're trying to perform your own custom SQL distinct Query you'll need to use the Custom SQL APIs, e.g:
var sql = q.ToSelectStatement().Replace(what,with);
var results = Db.SqlList<WatchedUrlScanResult>(sql);

Is this type of query safe from sql injection?

let tableName = req.body.tableName
let colName = req.body.col1+","+req.body.col2
sqlString = INSERT INTO ${tableName}(${colName}) VALUES ($1,$2) RETURNING *
No, you are using user's input as is inside a SQL query.
Use some kind of query builder like knex, which has a built in way of escaping user's input properly.

How to get a SELECT DISTINCT on a SelectMulti query in ServiceStack OrmLite?

I'm trying to get a distinct result set of tuples, but the Distinct never gets added to query.
Example
List<Tuple<Alpha, Beta>> results;
var q = dbConn.From<Alpha>()
.Join<Alpha, Beta>((a, b) => a.Id == b.AlphaId)
...
... more joins and Wheres
...
.SelectDistinct();
results = dbConn.SelectMulti<Alpha, Beta>(q);
Adding the SelectDistinct, or not, make no difference to the outputted SQL and hence results.
How do I get SelectMulti to work with Distinct?
Thanks.
I've just added support for this in this commit where if .SelectDistinct() is used in the SqlExpression<T> then it will execute the SQL query using SELECT DISTINCT, e.g:
var results = dbConn.SelectMulti<Alpha, Beta>(q.SelectDistinct());
This change is available from v5.4.1 that's now available on MyGet.

OrmLite and Common table expressions

I'm trying to run a similar query:
sql = #"with t(id) as (select 1 )
select * from Project
where id > (select id from t)";
var projects = this.Db.Query<Project>(sql).ToArray();
For some reason the OrmLite decides to treat the sql as as "where" clause, so what ends up running is something like this:
select field1, field2 from project where with t(id) .....
Does it look for a "select" at a starting position of the query ?
Short of creating a view - is there a way to run query with CTE ?
Use the db.Sql* API's for raw SQL Queries, e.g:
var projects = db.SqlList<Project>(sql);

SubSonic.SqlQuery incorrectly generated when using Where()

I am using version 2.1 of SubSonic. I am trying to build to build a relatively simple query where I get a list of Roles for a User using UserId as a parameter. (UserId is a string...)
SubSonic.SqlQuery sel = new SubSonic.Select().From(Data.Tables.Role).InnerJoin(Data.Tables.UserRole, Data.UserRole.Columns.RoleId, Data.Tables.Role, Data.Role.Columns.Id).InnerJoin(Data.Tables.User, Data.User.Columns.Id, Data.Tables.UserRole, Data.UserRole.Columns.UserId).Where("[dbo].[User].[Id]").IsEqualTo(userId);
this generates the query
SELECT [dbo].[Role].[Id], [dbo].[Role].[PID], [dbo].[Role].[Name]
FROM [dbo].[Role]
INNER JOIN [dbo].[UserRole] ON [dbo].[Role].[Id] = [dbo].[UserRole].[RoleId]
INNER JOIN [dbo].[User] ON [dbo].[UserRole].[UserId] = [dbo].[User].[Id]
WHERE [dbo].[User].[Id] = #[dbo].[User].[Id]0
which fails. If I replace the Where with .Where(Data.User.Columns.Id) this generates the query
SELECT [dbo].[Role].[Id], [dbo].[Role].[PID], [dbo].[Role].[Name]
FROM [dbo].[Role]
INNER JOIN [dbo].[UserRole] ON [dbo].[Role].[Id] = [dbo].[UserRole].[RoleId]
INNER JOIN [dbo].[User] ON [dbo].[UserRole].[UserId] = [dbo].[User].[Id]
WHERE [dbo].[Role].[Id] = #Id0
which uses the Role table in the Where clause instead of the User table.
Is this a bug, or am I doing something incorrectly? What would be the correct way to do this? Thanks.
This is fixed in version 2.2 - I would suggest upgrading.

Resources