Sql in ormlite servicestack - c#

I use ormlite with servicestack and I have got this problem.
I have saved a list of string in a column of my db so I want to do a select sql like this:
Select top 1 *
From MyTable
Where MyVariable In (MyListSavedInDb)
var orders = db.Select<Order>(o => Sql.In(o.Ldv, o.Waybills));
Where o.Ldv is a string and o.Waybills is a list of string saved on db
Any solutions ?

You can't query a blobbed field with server-side SQL, best you can do is a fuzzy string index search like:
var q = db.From<Order>();
q.Where($"CHARINDEX({q.Column<Order>(x=>x.Ldv)},{q.Column<Order>(x=>x.Waybills)}) > 0")
.Take(1);
var order = db.Single(q);
But essentially you shouldn't be blobbing any fields that you want to perform server-side SQL queries on.
A more typed and robust approach would be to perform the final query on a blobbed collection on the client after you've filtered the resultset, e.g:
var orders = db.Select(q);
var order = orders.FirstOrDefault(x => x.Waybills.Contains(term));
But as this query is done on the client you'll want to ensure it's being done on a limited filtered resultset.

Related

How to write between condition in c# using TableQuery in Azure storage

I want to apply between conditions using tablequery azure in C#.
I give one SQL sentence as below -
select * from CardEvents where (CAST('20210327' AS DATE) BETWEEN CAST(EventStartDate AS DATE) AND CAST(EventEndDate AS DATE))
Please give me result in tablequery azure format.
Please try the query below and feel free to modify it as per your need:
//other code
var filter1 = TableQuery.GenerateFilterConditionForDate("xxx", QueryComparisons.GreaterThanOrEqual, DateTimeOffset.Parse("xx"));
var filter2 = TableQuery.GenerateFilterConditionForDate("xxx", QueryComparisons.LessThanOrEqual, DateTimeOffset.Parse("xx"));
string combinedFilter = TableQuery.CombineFilters(filter1, TableOperators.And, filter2);
TableQuery query = new TableQuery().Where(combinedFilter);
//other code
Note: in table query, this query which is not based on PartitionKey will cause table scan, and it may take a few more time. So if possible, please follow this doc to use the most proper way to query your table data.

Entity Framework append where clause to SqlQuery call

I have the following raw query being executed through Entity Framework via a SqlQuery call on the DbSet:
public IEnumerable<TEntity> GetComplicatedData<TEntity>()
{
return database
.Set<TEntity>()
.SqlQuery("SELECT * FROM <Complicated Query Here>");
}
...
var count = GetComplicatedData<Item>()
.Where(f => f.OwnerID == 5)
.Count();
This works, but is very slow due to the fact that SqlQuery executes immediately without the Where getting applied.
Is there any way to call SqlQuery in such a way that the Where gets applied server-side?
Essentially, I want Entity Framework to generate a store query like:
SELECT
<Columns>
FROM
(
SELECT * FROM <Complicated Query Here>
) a
WHERE a.OwnerID = 5
Or, is there a way to translate my where expression into a query that I can append manually (a.k.a, without manually writing a SQL query, the where clause is not always that simple)?
This cannot be done with LINQ methods, because "raw" queries are of type DbRawSqlQuery<TElement>, which lacks support required for "composing" dynamic queries with Where.
If you are interested in counting items, you could work around the issue by taking a condition:
public int CountComplicatedData<TEntity>(Func<TEntity,bool> condition) {
return database
.Set<TEntity>()
.SqlQuery("SELECT * FROM <Complicated Query Here>")
.Count(condition);
}

Setting WHERE condition to use Ids.Contains() in ExecuteSqlCommand()

I'm using Entity Framework and I want to perform a bulk update. It is way too inefficient to load each row, update those rows, and then save them back to the database.
So I'd prefer to use DbContext.Database.ExecuteSqlCommand(). But how can I use this method to update all those rows with an ID contained in my list of IDs?
Here's what I have so far.
IEnumerable<int> Ids;
DbContext.Database.ExecuteSqlCommand("UPDATE Messages SET Viewed = 1 WHERE Id IN (#list)", Ids);
I realize I could manually build a string with the correct query, but I'd prefer to pass my parameters as is generally recommended.
Is there any way to make that happen?
You can still build the parameters and include them in the parameterized query.
The query would look something like this when generated
UPDATE Messages SET Viewed = 1 WHERE Id IN (#p0, #p1, #p2, ..., #pn)
So given
IEnumerable<int> Ids;
Then
var parameters = Ids.Select((id, index) => new SqlParameter(string.Format("#p{0}", index), id));
var parameterNames = string.Join(", ", parameters.Select(p => p.ParameterName));
var query = string.Format("UPDATE Messages SET Viewed = 1 WHERE Id IN ({0})", parameterNames);
int affected = DbContext.Database.ExecuteSqlCommand(query, parameters.ToArray());
Instead of generating query string with exact values, you can generate query string with as many parameters as you have.
So you'll get smth like:
DbContext.Database.ExecuteSqlCommand("UPDATE Messages SET Viewed = 1 WHERE Id IN (#p0,#p1,#p2,...,#pN)", Ids);
by smth like this:
var paramsDef = string.Concat(Ids.Select(x=>$"{(Ids.IndexOf(x) > 0 ? "," : "")}p{Ids.IndexOf(x)}"));
DbContext.Database.ExecuteSqlCommand($"UPDATE Messages SET Viewed = 1 WHERE Id IN {paramsDef}", Ids);
Some links I found people doing similar with SqlCommand:
http://www.svenbit.com/2014/08/using-sqlparameter-with-sqls-in-clause-in-csharp/
http://nodogmablog.bryanhogan.net/2016/01/parameterize-sql-where-in-clause-c/

How use wild card in table name for GetSchema method?

I want query all the existing tables whose name begin with specific string in database using oledb GetSchema method.
In other words I am looking for equivalent of the following sql query:
SELECT * FROM information_schema.tables WHERE table_name LIKE 'customer%'
Something like:
String[] tableRestrictions = new String[4];
tableRestrictions[2] = "%customer";
DataTable customerTables = conn.GetSchema("Tables", tableRestrictions );
In this case the table name I want to query from is Dynamic. Therefore I needed to get the whole table name first.
It seems there is not efficient way to do that but using an iteration.
I came to this conclusion that using Linq provides the neatest solution(Thanks to Tim's answer to a similar case):
// Get the tables using GetSchema:
dtbTables = dbConnection.GetSchema("tables");
// use linq to get the table whose name matches the criteria:
DataRow recSpecificTable = dbConnection.GetSchema("Tables").AsEnumerable()
.Where(r => r.Field<string>("TABLE_NAME")
.StartsWith("customer")).FirstOrDefault();
// Now the table name I am looking for:
tableName = Convert.ToString(recSpecificTable["TABLE_NAME"]).Trim();

NHibernate (c#.net) - automatically map results of a SQLQuery to a dto object

Up to now (with NHibernate) I've used entity mapping and not really got involved with creating raw sql queries - but somethings come up where I need to do exactly that.
The problem I have is I want to automatically map the columns aliases of my query to a Dto object.
This works, but i have to specify the column alias' in the order of the query.
SQL
string sql = "select mycol1 as ColumnOne from mytable";
NHibernate Query
var query = session.CreateSQLQuery(sql)
.AddScalar("ColumnOne", NHibernateUtil.Int32)
.SetResultTransformer(
NHibernate.Transform.Transformers.AliasToBean<MyDtoObject>()
);
MyDtoObject
public class MyDtoObject
{
public int ColumnOne {get;set;}
}
But is there a way to making NHibernate automate the mapping between the columns in the query and the Dto without creating a mapping class?
I've seen some examples of using aliases in the query e.g.
string sql = "select mycol1 as {ColumnOne} as ColumnOne from mytable"; /// ???
But cannot get this to work as the alias {ColumnOne} appear not to be replaced before being sent to the db as a sql statement.
Any idea?
TIA
Sam
Maybe System.Linq.Dymanic will help:
use System.Linq.Dynamic;
string ColumnAlisName = "ColumnOne";
var query = mytable.Select(String.Format("new (mycol1 as {0})",ColumnAlisName));

Categories

Resources