Dapper, SqlBuilder extension and Order By descending - dapper

I am trying to build a simple query that retrieves data in descending order using Dapper. The database is MySql if that's important.
This is the code I used:
var builder = new SqlBuilder();
var sql = #$"SELECT * FROM table t /**orderby**/ LIMIT #paramSkip, #paramTake";
var template = builder.AddTemplate(sql);
builder.OrderBy("#paramOrderBy DESC", parameters: new
{
paramOrderBy = orderBy,
});
// Limit
builder.AddParameters(parameters: new
{
paramSkip = skip,
paramTake = take
});
return Connection.QueryAsync<TableModel>(
template.RawSql, template.Parameters,
transaction: Transaction
);
This always returns data in ascending order. DESC is just ignored. I tried using the DESC keyword in the query or as parameter but the result was the same.
Only thing that worked was putting order parameters and DESC keyword in query itself (by string interpolation)
(Edit: Typos and text simplification)

You need your query to look something like this:
... ORDER BY <Column name> DESC ...
A column name cannot be parameterized, so you need to insert it into the query something like this:
builder.OrderBy($"{orderBy} DESC");
If your orderBy originates from the user in any way, be sure to sanitize it first to prevent SQL injection. You could - for instance - keep a list of valid column names and validate against it.

Related

Using SqlKata from an existing Query

I have existing queries used for jobs that run within services to generate reports. Simple things like
"Select * from Transactions"
The jobs will then append parameters to these queries based on preset rules, like Date>Yesterday etc. SqlKata looks like it can do this but I'm not sure how to instantiate the Query object from an existing query. Is something like this possible?
Dim Qry as new Query("Select * from Transactions").OrderByDesc("Date")
Qry.Where("Date", ">", Date.Now().AddDays(-1))
return Qry.Get()
The closest thing that you can do in this case is to wrap the inner query and add conditions on top of it, you can use the SubQuery or CTE approach here.
Something like this, this in C# but the idea is the same.
var existingSql = "select * from transactions";
var query = new Query().FromRaw($"({existingSql}) as inner")
.Where("date", ">=", DateTime.UtcNow.Date);
checkout this example on playground

Trying to Count data with the same suffix in a table

I have the code below and I'm trying to count data with the suffix "Fertilizer" and "pesticide" from a table in my SQL server database. The code is not working, what can be the problem
private string GetFarmInputCount()
{
string ret = "_ _";
string query = "SELECT Count(*) FROM Loan WHERE Name LIKE 'Fertilizer' AND 'Pesticide'";
DataTable dt = QueryDatabase(query);
foreach(DataRow row in dt.Rows)
{
ret = row[0].ToString();
}
return ret;
}
You need to add wildcards to the strings you are trying to match so that SQL Server knows where to match additional characters. In this case, the wildcard is %, and you want to match cases where your strings are suffixes, so you need to put the wildcard at the beginning. Your query then should look like this:
SELECT Count(*) FROM Loan WHERE Name LIKE '%Fertilizer' OR '%Pesticide'"
You can find more information in the Microsoft docs on how pattern matching with LIKE works, including other types of wildcards you can use.

Sort a LINQ with another LINQ in MVC

Using SQL Server Management
Using MVC VS 2013 for Web
Being in a Controller
Here materialnumb it's a LINQ query that always return only one value.
Being the following...
var materialnumb = (from r in db.MaterialNumber
where r.MaterialNumber == 80254842
select r.MaterialNumber);
I have another LINQ query from a SQL view that involves several other tables with inner join statements and so on (which includes the previous table db.MaterialNumber) that goes like this:
var query = (from r in db.SQLViewFinalTable
where r.MaterialNumber == Convert.ToInt32(materialnumb.MaterialNumber)
select r
I want to sort all the materials by the retrieved material number from the first query but it drops the following error when I try to pass the query as a model for my View:
LINQ to Entities does not recognize the method 'Int32
ToInt32(System.String)' method, and this method cannot be translated
into a store expression.
I assume this is because the query is an object even if its has just one value so it can't be converted into a single Int32.
Even more, the query it's not being executed, it's just a query...
So, how can achieve my goal?
Additional information: I tried to convert the query outside the "final" query. It still doesn't work.
Additional information: This is just an example, the true query actually has several more other querys embedded and this other querys have also other querys in them, so I need a practical way.
Additional information: I have also tried to convert the query into a string and then again into an int.
Try this:
var materialnumb = (from r in db.MaterialNumber
where r.MaterialNumber == 80254842
select r.MaterialNumber).FirstOrDefault();
var query = from r in db.SQLViewFinalTable
where r.MaterialNumber == materialnumb
select r
But I can not get whay are you filtering by 80254842 and selecting the same value? You can do directly:
var query = from r in db.SQLViewFinalTable
where r.MaterialNumber == 80254842
select r

Accessing new field value generated in SQL via dbContext

I'm using dbContext and I am running a SQL query that is rather complex (just showing a simple example below), so to avoid having to run the query twice to get a count, I am using COUNT AS to return the total number of records as per other advice on this site.
But, I haven't been able to figure out how to access the resulting property:
using (var db = new DMSContext())
{
string queryString = "select *, COUNT(1) OVER() AS TotalRecords FROM DMSMetas";
var Metas = db.DMSMetas.SqlQuery(queryString).ToList();
for (int i = 0; i <= Metas.Count - 1; i++)
{
var Item = Metas[i];
if (i == 0)
{
//Want to do this, but TotalRecords not part of the DMSMeta class. How to access the created column?
Console.WriteLine("Total records found: " + Item.TotalRecords);
}
}
}
In the sample above, the SQL query generates the extra field TotalRecords. When I run the query in Management Studio, the results are as expected. But how do I access the TotalRecords field through dbContext?
I also tried including the TotalRecords field as part of the DMSMeta class, but then the SQL query fails with the error that the TotalRecords field is specified twice. I tried creating a partial class for DMSMeta containing the TotalRecords field, but then the value remains the default value and is not updated during the query.
I also tried the following:
db.Entry(Item).Property("TotalRecords").CurrentValue
But that generated an error too. Any help would be much appreciated - I am sure I am missing something obvious! All I want is to figure out a way to access the total number of records returned by the query
you have to create a new class (not an entity class but a pure DAO class) DMSMetaWithCount (self explanatory ?) and then
context.Database.SqlQuery<DMSMetaWithCount>("select *, COUNT(1) OVER() AS TotalRecords FROM DMSMetas");
please note that
imho, select * is ALWAYS a bad practice.
you will have no tracking on the not entity new class

How to select columns with other name in linq?

I select my records in SQL Server Query as you seen below:
SELECT ProductName 'Some Name1' ,
Payment 'Some Name2'
FROM dbo.PrefactorProduct
Is there a way to select records like that in linq queries?
You can project result from your query to an Anonymous type and use different alias/field names for your fields.
var query = db.PrefactorProduct
.Select(r=> new
{
SomeName1 = r.ProductName,
SomeName2 = r.Payment
});
But if you are trying to format your result set for displaying purpose then you should look in to assigning column names for your grid/ data container.

Resources