var insertReq:SQLStatement = new SQLStatement();
insertReq.addEventListener(SQLErrorEvent.ERROR, dbErrorHandler);
insertReq.sqlConnection = conn;
insertReq.text = "INSERT INTO table1 (inputTime) VALUES (DATETIME('now'))";
insertReq.execute();
insertReq.text = "SELECT last_insert_rowid() as ID";
insertReq.execute();
var lastInsertId:int = insertReq.getResult().data[0].id;
trace(lastInsertId);
I made a local database and i am trying to insert some data but
I get lastInsertId zero?! Where I mess up things!?
You don't need to make additional execution of query for retrieving last inserted row's id.There is a built-in .lastInsertRowID property of SQLResult class for that purpose. Just use it like this:
var insertReq:SQLStatement = new SQLStatement();
insertReq.addEventListener(SQLErrorEvent.ERROR, dbErrorHandler);
insertReq.sqlConnection = conn;
insertReq.text = "INSERT INTO table1 (inputTime) VALUES (DATETIME('now'))";
insertReq.execute();
var lastInsertId:int = insertReq.getResult().lastInsertRowID;
trace(lastInsertId);
Related
This question already has answers here:
How do I return multiple result sets with SqlCommand?
(7 answers)
Closed 1 year ago.
I have a user-defined stored procedure which returns multiple actual tables as result set:
CREATE PROCEDURE uspDemo
(#UserID BIGINT = 0,
#IsAdmin BIT = 0,
#Title VARCHAR(120) = '')
AS
BEGIN
------Retrieve Posts------
SELECT *
FROM tblPost AS MP
INNER JOIN tblUserProfile AS UP ON UP.ID = MP.UserID
WHERE UP.ID = #UserID
AND ((#IsAdmin = 0 AND MP.IsDeleted = 0 AND MP.IsApproved = 1)
OR (#IsAdmin = 1 OR MP.IsDeleted = 0 OR MP.IsApproved = 1))
----- Retrieve Tags------
SELECT *
FROM tblTagMasters AS MT
INNER JOIN tblPostTags AS MP ON MT.TagID = MP.TagID
--------Retrieve User likes-----
SELECT *
FROM tblUserLikes AS UV
INNER JOIN tblPost AS MP ON MP.PostId = UV.PostId
END
How to translate in ASP.NET MVC? Please help me.
Basically, you need something like this:
// define connection string and command for your query
string connectionString = "....."; // typically load from config
string storedProcedureName = "dbo.uspDemo";
// put your disposable ADO.NET objects into proper "using ()" blocks
using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand(storedProcedureName, conn))
{
cmd.CommandType = CommandType.StoredProcedure;
// define the parameters
cmd.Parameters.Add("#UserID", SqlDbType.BigInt).Value = .....;
cmd.Parameters.Add("#IsAdmin", SqlDbType.Bit).Value = .....;
cmd.Parameters.Add("#Title", SqlDbType.VarChar, 120).Value = ".....";
// open connection
conn.Open();
// execute stored procedure to get the data reader
using (SqlDataReader reader = cmd.ExecuteReader())
{
// read the first set of data returned
while (reader.Read())
{
// read the values, construct an object from it, store the object into a list or something
}
// get the next set of result data
reader.NextResult();
// read the second set of data returned
while (reader.Read())
{
// read the values, construct an object from it, store the object into a list or something
}
// get the next set of result data
reader.NextResult();
// read the third set of data returned
while (reader.Read())
{
// read the values, construct an object from it, store the object into a list or something
}
}
conn.Close();
}
I leave the remaining details up to you - do some research!
I have a procedure which returns the identity of the record added. I am using Entity Framework to call the procedure and retrieve the value, but it is always 0.
This is the code - can you figure out why it is not returning the identity value?
C# Entity Framework domain code:
var cNumber = new SqlParameter("CNumber", acctSl.cNumber);
var fId = new SqlParameter("FId", acctSl.FId);
var splAmt = new SqlParameter("SplAmt", acctSl.SplAmt);
var frDt = new SqlParameter("FrDt", acctSl.FrDate);
var toDt = new SqlParameter("ToDt", acctSl.ToDate);
var user = new SqlParameter("User", acctSl.User);
var id = new SqlParameter("Id", "")
{
Direction = ParameterDirection.Output,
SqlDbType = SqlDbType.VarChar
};
var sql = "EXECUTE [dbo].[InsertAcctSpl] #CNumber, #FID, #SplAmt, #FrDt, #ToDt, #User, #Id OUTPUT";
var result = DbContext.Database.ExecuteSqlRaw(sql, cNumber, fId, splAmt, frDt, toDt, user, id);
int rowsAffected;
var yourOutput = Convert.ToInt32(id.Value);
if (result > 0)
{
acctSl.AcctId = yourOutput;
}
else
{
acctSl.AcctId = 0;
}
SQL Server procedure:
ALTER PROCEDURE [dbo].[InsertAccountsSpend]
#CNumber varchar(15),
#FId bigint,
#SplAmt money,
#FrDt date,
#ToDt date,
#User bigint,
#Id bigint OUTPUT
AS
INSERT INTO AcctSpend (CNmbr, FID, SplAmt, FrDt, ToDt,
Cr8Dt, Cr8User_ID, UpdtDt, UpdtUser_ID)
VALUES (#CNumber, #FId, #splAmt, #FroDt,# ToDt,
GETDATE(), #User, GETDATE(), #User)
SET #id = SCOPE_IDENTITY()
RETURN #id
The issue was with the data type it needed be long
var id = new SqlParameter("Id", "")
{
Direction = ParameterDirection.Output,
**SqlDbType = SqlDbType.BigInt**
};
Your problem seems to be with this section of your code:
int rowsAffected;
var yourOutput = Convert.ToInt32(id.Value);
if (rowsAffected > 0)
{
acctSl.AcctId = yourOutput;
}
else
{
acctSl.AcctId = 0;
}
You are basing your if-else logic off of the rowsAffected variable, but that variable is never assigned the value from your stored procedures output. Since rowsAffected is declared as an int type variable, it cannot be null, so it is automatically set to 0.
To get the actual value for rowsAffected you will need to utilize the data returned in your result variable that you have declared here:
var result = DbContext.Database.ExecuteSqlRaw(sql, cNumber, fId, splAmt, frDt, toDt, user, id);
EDIT
It appears that the syntax around your id SQL parameter object is incorrect. Try creating this object in the following manner:
var id = new SqlParameter
{
ParameterName = "Id",
DbType = System.Data.DbType.String,
Direction = System.Data.ParameterDirection.Output
};
I have a stored procedure in SQL Server 2012:
CREATE PROCEDURE GetImmediateManager
#managerID INT OUTPUT
AS
BEGIN
SET #managerID = 6;
SELECT *
FROM Roles;
END
When I remove select * from Roles; the output value (#managerID) is returned correctly to my C# code. But when the procedure has select * .., the value returned by output parameter is null.
How can I return select and output at the same time?
In C# my code looks like this:
dbContext.Database.OpenConnection();
DbCommand cmd = dbContext.Database.GetDbConnection().CreateCommand();
cmd.CommandTimeout = 15;
cmd.CommandText = "GetImmediateManager";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
var rowsCountParam = new SqlParameter("#managerID", System.Data.SqlDbType.Int);
rowsCountParam.Direction = ParameterDirection.Output;
cmd.Parameters.Add(rowsCountParam);
using (var reader = cmd.ExecuteReader())
{
tasks = reader.MapToList<TaskManagerTask>();
//rowsCount = (int)rowsCountParam.Value;
}
The simplistic answer is to add #managerID to your select statement
For a less simplistic perhaps the following, I changed the names a bit to reflect the use, get parameter after it closes.
var managerIDParam = new SqlParameter("#managerID", System.Data.SqlDbType.Int);
managerIDParam.Direction = ParameterDirection.Output;
cmd.Parameters.Add(managerIDParam);
using (var reader = cmd.ExecuteReader())
{
tasks = reader.MapToList<TaskManagerTask>();
}
int managerIDParamUsed = (int)managerIDParam.Value;
I have encrypted existing data using the SQL Server 2016 always encrypt method, one of column we have is NULLABLE but while insert from screen its not accepting either NULL or empty String. how to make it work if encrypted column is not mandatory on screen?
The error that you are seeing is incorrect, please ensure that you are passing the parameter correctly. Here is some sample code on how to do so.
Schema:
CREATE TABLE [dbo].[SO](
[ssn] [nvarchar](9) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [CEK_Auto1], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL
)
GO
CREATE PROCEDURE dbo.insertSP #ssn nvarchar(9)
AS
INSERT INTO [dbo].[SO] ([SSN]) VALUES (#SSN);
GO
C# code:
SqlConnectionStringBuilder strbldr = new SqlConnectionStringBuilder();
strbldr.DataSource = ".";
strbldr.InitialCatalog = #"exptdb";
strbldr.IntegratedSecurity = true;
strbldr.ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Enabled;
string ssn = "";
using (var conn = new SqlConnection(strbldr.ConnectionString))
using (var command = conn.CreateCommand()) {
command.CommandType = CommandType.StoredProcedure;
command.CommandText = #"dbo.insertSP";
SqlParameter paramSSN = command.CreateParameter();
paramSSN.ParameterName = "#ssn";
paramSSN.SqlDbType = SqlDbType.NVarChar;
paramSSN.Direction = ParameterDirection.Input;
paramSSN.Value = ssn;
paramSSN.Size = 9;
command.Parameters.Add(paramSSN);
conn.Open();
command.ExecuteNonQuery();
}
Note, that in the scenario mentioned above, if
string ssn = "";
then the query succeeds, however if
string ssn = null;
you should see a failure on execution
Additional information: Procedure or function 'insertSP' expects
parameter '#ssn', which was not supplied.
This failure will occur even when ssn column is plaintext
You can insert null value in the encrypted column as follows, since null values are not encrypted:
using (var conn = new SqlConnection(strbldr.ConnectionString))
using (var command = conn.CreateCommand()) {
command.CommandText = #"INSERT INTO [dbo].[SO] ([SSN]) VALUES (null)";
conn.Open();
command.ExecuteNonQuery();
}
I am trying to write a dapper query for IN clause, but it's not working throwing casting error saying "Conversion failed when converting the nvarchar value 'A8B08B50-2930-42DC-9DAA-776AC7810A0A' to data type int." . In below query fleetAsset is Guid converted into string.
public IQueryable<MarketTransaction> GetMarketTransactions(int fleetId, int userId, int rowCount)
{
//Original EF queries which I am trying to convert to Dapper
//var fleetAsset = (from logicalFleetNode in _context.LogicalFleetNodes
// where logicalFleetNode.LogicalFleetId == fleetId
// select logicalFleetNode.AssetID).ToList();
////This query fetches guid of assetprofiles for which user having permissions based on the assets user looking onto fleet
//var assetProfileIds = (from ap in _context.AssetProfileJoinAccounts
// where fleetAsset.Contains(ap.AssetProfile.AssetID) && ap.AccountId == userId
// select ap.AssetProfileId).ToList();
var fleetAsset = _context.Database.Connection.Query<string>("SELECT CONVERT(varchar(36),AssetID) from LogicalFleetNodes Where LogicalFleetId=#Fleetid",
new { fleetId }).AsEnumerable();
//This query fetches guid of assetprofiles for which user having permissions based on the assets user looking onto fleet
var sql = String.Format("SELECT TOP(#RowCount) AssetProfileId FROM [AssetProfileJoinAccounts] AS APJA WHERE ( EXISTS (SELECT " +
"1 AS [C1] FROM [dbo].[LogicalFleetNodes] AS LFN " +
"INNER JOIN [dbo].[AssetProfile] AS AP ON [LFN].[AssetID] = [AP].[AssetID]" +
" WHERE ([APJA].[AssetProfileId] = [AP].[ID]) " +
" AND ([APJA].[AccountId] = #AccountId AND LogicalFleetId IN #FleetId)))");
var assetProfileIds = _context.Database.Connection.Query<Guid>(sql, new { AccountId = userId, FleetId = fleetAsset, RowCount=rowCount });
Dapper performs expansion, so if the data types match, you should just need to do:
LogicalFleetId IN #FleetId
(note no parentheses)
Passing in a FleetId (typically via an anonymous type like in the question) that is an obvious array or list or similar.
If it isn't working when you remove the parentheses, then there are two questions to ask:
what is the column type of LocalFleetId?
what is the declared type of the local variable fleetAsset (that you are passing in as FleetId)?
Update: test case showing it working fine:
public void GuidIn_SO_24177902()
{
// invent and populate
Guid a = Guid.NewGuid(), b = Guid.NewGuid(),
c = Guid.NewGuid(), d = Guid.NewGuid();
connection.Execute("create table #foo (i int, g uniqueidentifier)");
connection.Execute("insert #foo(i,g) values(#i,#g)",
new[] { new { i = 1, g = a }, new { i = 2, g = b },
new { i = 3, g = c },new { i = 4, g = d }});
// check that rows 2&3 yield guids b&c
var guids = connection.Query<Guid>("select g from #foo where i in (2,3)")
.ToArray();
guids.Length.Equals(2);
guids.Contains(a).Equals(false);
guids.Contains(b).Equals(true);
guids.Contains(c).Equals(true);
guids.Contains(d).Equals(false);
// in query on the guids
var rows = connection.Query(
"select * from #foo where g in #guids order by i", new { guids })
.Select(row => new { i = (int)row.i, g = (Guid)row.g }).ToArray();
rows.Length.Equals(2);
rows[0].i.Equals(2);
rows[0].g.Equals(b);
rows[1].i.Equals(3);
rows[1].g.Equals(c);
}