PetaPoco INSERT with # in the string - tsql

I want to Execute a line of SQL which looks like this:
conn.Open();
var db = new PetaPoco.Database(conn);
var sql = "INSERT INTO FOO (name) VALUES ( 'foo#bar.com')";
var response = db.Execute(sql);
The problem is that PetaPoco thinks #bar is a parameter. Is there a way to tell it not to treat any #'s specially? My super lame work around was to replace "#" with "at". I live with this shame.

"You are doing it wrong"™
To avoid SQL Injection attacks, and other minuances concatenting strings, you should use parameters:
var response = db.Execute("INSERT INTO FOO (name) VALUES (#0)", "foo#bar.com");
Wrong way, but works at least:
var response = db.Execute("INSERT INTO FOO (name) VALUES ('foo##bar.com')",

You need to use two # characters to escape it. I think this should work:
var sql = "INSERT INTO FOO (name) VALUES ( 'foo##bar.com')"

Related

How can I get the name of procedure in Nim?

I am trying to write a macro for debug print in the Nim language.
Currently this macro adds filename andline to the output by instantiationInfo().
import macros
macro debugPrint(msg: untyped): typed =
result = quote do:
let pos = instantiationInfo()
echo pos.filename, ":", pos.line, ": ", `msg`
proc hello() =
debugPrint "foo bar"
hello()
currently output:
debug_print.nim:9: foo bar
I would like to add the name of the procedure (or iterator) of the place where the macro was called.
desired output:
debug_print.nim:9(proc hello): foo bar
How can I get the name of procedure (or iterator) in Nim, like __func__ in C?
At runtime you can do getFrame().procname, but it only works with stacktrace enabled (not in release builds).
At compile-time surprisingly I can't find a way to do it. There is callsite() in macros module, but it doesn't go far enough. It sounds like something that might fit into the macros.LineInfo object.
A hacky solution would be to also use __func__ and parse that back into the Nim proc name:
template procName: string =
var name: cstring
{.emit: "`name` = __func__;".}
($name).rsplit('_', 1)[0]
building on answer from #def- but making it more robust to handle edge cases of functions containing underscores, and hashes containing trailing _N or not
also using more unique names as otherwise macro would fail if proc defines a variable name
import strutils
proc procNameAux*(name:cstring): string =
let temp=($name).rsplit('_', 2)
#CHECKME: IMPROVE; the magic '4' chosen to be enough for most cases
# EG: bar_baz_9c8JPzPvtM9azO6OB23bjc3Q_3
if temp.len>=3 and temp[2].len < 4:
($name).rsplit('_', 2)[0]
else:
# EG: foo_9c8JPzPvtM9azO6OB23bjc3Q
($name).rsplit('_', 1)[0]
template procName*: string =
var name2: cstring
{.emit: "`name2` = __func__;".}
procNameAux(name2)
proc foo_bar()=
echo procName # prints foo_bar
foo_bar()
NOTE: this still has some issues that trigger in complex edge cases, see https://github.com/nim-lang/Nim/issues/8212

Entity Framework Core, Stored Procedure

I am totally confused regarding how to use Stored Procedures using Entity Framework Core. If the stored procedure return an anonymous type, how do I retrieve the data? If the return type is not anonymous, what should I do? How do I add input/output parameters?
I am asking these questions because everywhere I look, I get a different answer. I guess EF Core is evolving rapidly and Microsoft is dabbling with a lot of ideas.
How do I add input/output parameters?
I'm going to answer this particular question of yours.
Below is a TSQL stored procedure with two input and two output parameters
CREATE PROCEDURE [dbo].[yourstoredprocedure]
-- Add the parameters for the stored procedure here
#varone bigint
,#vartwo Date
,#varthree double precision OUTPUT
,#varfour bigint OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- YOUR CODE HERE
SET #varthree = 10.02;
SET #varfour = #varone;
return;
END
Now To execute this stored procedure using Entity Framework Core
MyContext.Database
.ExecuteSqlCommand(#"EXECUTE [yourstoredprocedure] " +
" {0} " +
", {1} " +
",#varthree OUTPUT " +
", #varfour OUTPUT ", dataOne, dataTwo, outputVarOne, outputVarTwo);
var outputResultOne= outputVarOne.Value as double?;
var outputResultTwo= outputVarTwo.Value as long?;
You can pass your input simply using parameterized query as above. You can also create named parameters. such as for output parameters, I've created two named parameters as -
var outputVarOne = new SqlParameter
{
ParameterName = "#varthree ",
DbType = System.Data.DbType.Double,
Direction = System.Data.ParameterDirection.Output
};
var outputVarTwo = new SqlParameter
{
ParameterName = "#varfour ",
DbType = System.Data.DbType.Int64,
Direction = System.Data.ParameterDirection.Output
};
And This is how using EF Core you execute a stored procedure with input and output parameters. Hope this helps someone.
This solution provides methods that call a stored procedure and maps the returned value to a defined (non-model) entity. https://github.com/verdie-g/StoredProcedureDotNetCore
Microsoft address this issue:
"SQL queries can only be used to return entity types that are part of your model. There is an enhancement on our backlog to enable returning ad-hoc types from raw SQL queries." https://learn.microsoft.com/en-us/ef/core/querying/raw-sql
And here is the issue tracked in GitHub: https://github.com/aspnet/EntityFramework/issues/1862
you might use an extention like StoredProcedureEFCore
Then the usage is more intuitively.
List rows = null;
ctx.LoadStoredProc("dbo.ListAll")
.AddParam("limit", 300L)
.AddParam("limitOut", out IOutParam<long> limitOut)
.Exec(r => rows = r.ToList<Model>());
long limitOutValue = limitOut.Value;
ctx.LoadStoredProc("dbo.ReturnBoolean")
.AddParam("boolean_to_return", true)
.ReturnValue(out IOutParam<bool> retParam)
.ExecNonQuery();
bool b = retParam.Value;
ctx.LoadStoredProc("dbo.ListAll")
.AddParam("limit", 1L)
.ExecScalar(out long l);

VB Script in Access Variable not found

So I was advised that I could create some copy replace functionality to this form.
Here is my coding attempt in VB:
First I connect to DB using DAO. Then I use a SELECT statement that has been verified to pull the last record inserted into the DB. Then I try to refill the controls with the values from the query but I am getting reference errors.
Private Sub AutoFill_Click()
Dim db As DAO.Database, rs As DAO.Recordset
Dim strSQL As String
Set db = CurrentDb()
strSQL = "SELECT DISTINCTROW TOP 1 CPOrders.Cust, Customer.NAME, CPOrders.CP_Ref, CPOrders.Slsman, CPOrders.Date_opn, CPOrders.CPSmall, CPOrders.InvIssu, CPOrders.InvNo, CPOrders.InvDate, CPOrders.DueDate, CPOrders.ETADate, CPOrders.Closed, CPOrders.BuyerRef, CPOrders.ToCity, CPOrders.ToState, CPOrders.ToCtry, CPOrders.ToPort, CPOrders.Supplier, CPOrders.Origin, CPOrders.Product, CPOrders.GradeType, CPOrders.NoUnits, CPOrders.Pkg, CPOrders.Qty, CPOrders.TotSale, CPOrders.TotCost, CPOrders.GrMargin, CPOrders.[Sale$/Unit], CPOrders.[Cost$/Unit], CPOrders.OceanCost, CPOrders.OceanNotes, CPOrders.BLadingDate, CPOrders.USAPort, CPOrders.FOBCost, CPOrders.FASExportVal, CPOrders.InlandFrt, CPOrders.CommodCode, CPOrders.Notes FROM Customer INNER JOIN CPOrders ON Customer.[CUST_#] = CPOrders.Cust ORDER BY CPOrders.CP_Ref desc;"
Set rs = db.OpenRecordset(strSQL, dbOpenDynaset, dbReadOnly)
rs.MoveFirst
CP_Ref.ControlSource = rs!CP_Ref
Slsman.ControlSource = rs!Slsman
CPSmall.ControlSource = rs!CPSmall
InvIssu.ControlSource = rs!InvIssu
InvDate.ControlSource = rs!InvDate
DueDate.ControlSource = rs!DueDate
Closed.ControlSource = rs!Closed
rs.Close
db.Close
The control source reference picks up and autocompletes the word.
I would think that as it stands. although i'm not filling all the values with records from my SELECT statement that it would populate but instead i get things like #NAME? where the values should be. I also get a break in my code and it says "Invalid use of null"
Why? I appreciate your guys input and I can provider screenshots if necessary. I think this is involving the reference tie, but I'm not sure. Any help is much appreciated.
You are using the field names from the SELECT statement as if they were variables.
CP_Ref.ControlSource = rs("CP_Ref")
Slsman.ControlSource = rs("Slsman")
CPSmall.ControlSource = rs("CPSmall")
InvIssu.ControlSource = rs("InvIssu")
InvDate.ControlSource = rs("InvDate")
DueDate.ControlSource = rs("DueDate")
Closed.ControlSource = rs("Closed")
When you have that worked out, tackle the "Invalid use of null" problem by first identifying any fields that could potentially be NULL and using something like
SELECT Iif(IsNull([InvDate]), '', [InvDate]) As [InvDate], ...
in the SELECT statement to pass across a minimum of an empty string rather than a NULL value.

Anorm String Interpolation not replacing variables

We are using Scala Play, and I am trying to ensure that all SQL queries are using Anorm's String Interpolation. It works with some queries, but many are not actually replacing the variables before the query is executing.
import anorm.SQL
import anorm.SqlStringInterpolation
object SecureFile
{
val table = "secure_file"
val pk = "secure_file_idx"
...
// This method works exactly as I would hope
def insert(secureFile: SecureFile): Option[Long] = {
DBExec { implicit connection =>
SQL"""
INSERT INTO secure_file (
subscriber_idx,
mime_type,
file_size_bytes,
portal_msg_idx
) VALUES (
${secureFile.subscriberIdx},
${secureFile.mimeType},
${secureFile.fileSizeBytes},
${secureFile.portalMsgIdx}
)
""" executeInsert()
}
}
def delete(secureFileIdx: Long): Int = {
DBExec { implicit connection =>
// Prints correct values
println(s"table: ${table} pk: ${pk} secureFileIdx: ${secureFileIdx} ")
// Does not work
SQL"""
DELETE FROM $table WHERE ${pk} = ${secureFileIdx}
""".executeUpdate()
// Works, but unsafe
val query = s"DELETE FROM ${table} WHERE ${pk} = ${secureFileIdx}"
SQL(query).executeUpdate()
}
}
....
}
Over in the PostgreSQL logs, it's clear that the delete statement has not acquired the correct values:
2015-01-09 17:23:03 MST ERROR: syntax error at or near "$1" at character 23
2015-01-09 17:23:03 MST STATEMENT: DELETE FROM $1 WHERE $2 = $3
2015-01-09 17:23:03 MST LOG: execute S_1: ROLLBACK
I've tried many variations of execute, executeUpdate, and executeQuery with similar results. For the moment, we are using basic string replacement but of course this is bad because it's not using PreparedStatements.
For anyone else sitting on this page scratching their head and wondering what they might be missing...
SQL("select * from mytable where id = $id")
is NOT the same as
SQL"select * from mytable where id = $id"
The former does not do String interpolation whereas the latter does.
This is easily overlooked in the aforementioned docs as all the samples provided just happen to have a (non-related) closing parenthesis on them (like this sentence does)
Anorm String interpolation was introduced to pass parameter (e.g. SQL"Select * From Test Where id = $x), with interpolation arguments (e.g. $x) set on underlying PreparedStament according proper type conversion (see use cases on https://www.playframework.com/documentation/2.3.x/ScalaAnorm ).
Next Anorm release will also have the #$foo syntax to mix interpolation for parameter with standard string interpolation. This will allow to write DELETE FROM #$table WHERE #${pk} = ${secureFileIdx} and having it executed as DELETE FROM foo WHERE bar = ? (if literal table is "foo" and pk is "bar"), with literal secureFileIdx passed as parameter. See related pull request.
Until next revision is release, you can build Anorm from its master sources ti benefit from this change.

Passing query results in a viewbag

This seems like it should be so easy, but I've tried three or four ways to do it (but to no avail).
I'm just trying to put a query result in a viewbag and display it.
I've tried putting a model object list in a ViewBag:
var mesg = from MSG in lemondb.Messages
where MSG.msg == Membership.GetUser().ToString()
select MSG;
ViewBag.messages = MSG;
And then I try to spit it out in a .cshtml:
var message = (List<LemonTrader.Models.Message>)ViewBag.messages; // <--- fails here because it is a string
foreach ( var MSG in message )
{
#Html.Label(MSG.msg)<br />
}
But it says:
Cannot convert type
'System.Data.Entity.Infrastructure.DbQuery'
to
'System.Collections.Generic.List'
So it seems I'm using using the wrong template. How do I spit out a System.Entity.Infrastructure.DbQuery?
I've also tried passing the results through the Viewbag as a list of strings. (Is that a worse way to do it?)
var mesg = from MSG in lemondb.Messages
where MSG.msg == Membership.GetUser().ToString()
select MSG.msg;
ViewBag.messages = mesg;
And spitting it out as a string list:
foreach (var atext in ViewBag.messages as List<string>) { // gets hung up on foreach here (why???)
#Html.Label( atext )
}
And I get this:
Object reference not set to an
instance of an object.
And it points at the "foreach" keyword.
Does that mean there were no messages? Or what?
I wish there was a tutorial showing how to put queryresults in a ViewBag and how to get them out! I've seen tutorials that return an object.ToList() without respect to any kind of "where" mechanism, but no examples to pull out a few, relevant entries and display them.
Try
ViewBag.messages = MSG.ToList();
Also, System.Data.Entity.Infrastructure.DbQuery implements IEnumerable ( http://msdn.microsoft.com/en-us/library/system.data.entity.infrastructure.dbquery(v=vs.103).aspx ) so this should also work:
var message = (IEnumerable<LemonTrader.Models.Message>)ViewBag.messages;