Dynamic WHERE clause for BETWEEN with Dapper SQL Builder - dapper

I am trying to build dynamic WHERE clause with Dapper SQL builder. This works very well for all cases except BETWEEN. Have tried the below approach with BETWEEN (just like IN clause)
SqlBuilder sqlBuilder = new SqlBuilder();
var sqlTemplate = sqlBuilder.AddTemplate(#"Select * from tbl_example /**Where**/");
sqlBuilder.Where(#"Col BETWEEN #colparam", new { paramValue });
con.Query(sqlTemplate.RawSql, sqlTemplate.Parameters);
When using SQL Profiler, I observed that the query generated from dapper looks like
Select * from tbl_example Where Col BETWEEN (#colparam1,#colparam2)
NOTE:
paramValue is an array of Integer which i receive via API
I do understand that this can be written like Col BETWEEN #colparam1 AND #colparam2 or replacing BETWEEN with < and >

As you know, BETWEEN expects two parameters (#colparam1 AND #colparam2), but you're passing only a single one (#colparam).
Assuming that your array contains exactly the boundaries (min and max), try this:
sqlBuilder.Where(#"Col BETWEEN #val1 AND #val2", new { val1 = paramValue[0], val2 = paramValue[1] });

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

Working with the data from LinQ SQL query

Using VS 2013 (VB) and SQL server 2016.
I have linQ query that returns two columns from a database. The query is as follows.
Dim val = (From value In db.ngc_flowTypes
Where value.defaultValue IsNot Nothing
Select value.flowName, value.defaultValue)
The data it returns is a as follows.
I want to iterate through each row of the results and pass the values to certain variables. A ForEach statement doesnt seem to work as it just runs through once. I am sure this must be easy but I ont quite understand it. Am I getting the data returned in the best way via my query? Can I transpose the data to a data table in VB? so I can work with it easier?
The end result I want is string for each flow name with its corresponding default value (along with some other text). So something like this.
dim strsubmission as string = flowName + " has a value of " + defaultValue
Use ToDictionary.
Dim val = (From value In db.ngc_flowTypes
Where value.defaultValue IsNot Nothing
Select value).ToDictionary(Function(key) key.flowName,
Function(value) value.defaultValue)
This will actually execute the SQL of the linq on the database (approx. Select * From ngc_flowTypes Where defaultValue Is Not NULL), traverse each record into a key/value pair (flowName, defaultValue) and put it into a in-memory dictionary variable (val).
After that you can do whatever you like with the dictionary.
For Each flowName In val.Keys
Console.WriteLine("{0} has a value of {1}", flowName, val(flowName))
Next
Edit:
This will only work as long flowName is unique in table ngc_flowTypes

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

c++ builder: getting values via ADOQuery using SELECT

The question is as for delphi coders as for c++ builder coders, cuz I'm using the same components.
I'm trying to fill labels on the form by the data from database. I do a SELECT query via TADOQuery. But when I try to get a result, I always get an error like "ADOQuery1: Field 'count' not found".
'id' passed to the function is an autoincrement field value, which is EXACTLY exists in database (it was got via DBLookupComboBox). Also, executing the query manually to show result in DBGrid is successfull.
Querying without parameters and writing 'id' value to query string fails too.
What's the problem? Here's the code.
void TSellForm::LoadData(int id) {
TADOQuery* q = DataModule1->ADOQuery1;
q->Active = false;
try
{
q->SQL->Text = "select * from drugs where(id=:id)";
q->Parameters->ParamByName("id")->Value = IntToStr(id);
q->ExecSQL();
this->LabelAvail->Caption = q->FieldByName("count")->Value;
}
catch (Exception* e) {
MessageBox(NULL, PChar(WideString(e->Message)),
L"Exception", MB_OK|MB_ICONWARNING);
}
q->SQL->Clear();
}
ExecSQL is only used for SQL statements that don't return a recordset, and to determine the results you use RowsAffected.
For SELECT statements (which return a recordset), you use Open or set Active to true.
Also, count is a reserved word in most SQL dialects (as in SELECT Count(*) FROM ..., so if you have a column with that name you're going to need to escape it, typically by using either [] or double-quotes around it or by aliasing it in the SELECT itself.
ADOQuery1->Close();
ADOQuery1->SQL->Text= "SELECT * FROM reportTble WHERE (firstName =:firstName) " ;
ADOQuery1->Parameters->ParamByName("firstName")->Value = textBox->Text ;
ADOQuery1->Open();
This is how you can use ADOQuery

Resources