Asp.Net SqlDataReader value magically turns into null on attempt to access and use it - asp.net

I have an sql command that depends on the results of other sql commands. There are five sql commands in this chain, but the problem occurs in the 4th.
The 5th command must save data to the archive table. When it has to run and take the completion_date value from the 4th command, it throws a null reference exception. Actually it says, that Reader4[0] can't be read because it has null value. That's wrong because it has value, because in the database these queries work fine and also because the condition if (Reader4.HasRows == true) is true, it means that WHERE statement is true in the 4th command, which also includes checking the completion_date! What's wrong with this asp.net?
Command4 = new SqlCommand("SELECT trade_date FROM Schedule WHERE traider_id=#traiderID AND good_id=#goodID AND position_id=#positionID AND status_id=1 AND completion_date IS NOT NULL", Connection4); //note the completion_date check
Command4.Parameters.Add("#traiderID", Convert.ToInt32(Reader3[0]));
Command4.Parameters.Add("#positionID", CurrentPosition);
Command4.Parameters.Add("#goodID", Convert.ToInt32(Reader1[0]));
Reader4 = Command4.ExecuteReader();
if (Reader4.HasRows == true) //this check is done successfully
{
Command5 = new SqlCommand("INSERT INTO Archive (traider_id, good_id, completion_date) VALUES (#traiderID, #goodID, #completionDate)", Connection5);
Command5.Parameters.Add("#traiderID", Convert.ToInt32(Reader3[0]));
Command5.Parameters.Add("#goodID", Convert.ToInt32(Reader1[0]));
Command5.Parameters.Add("#completionDate", Convert.ToDateTime(Reader4[0])); //Here is the problem
Command5.ExecuteNonQuery();
}
Reader4.Close();

Where are you startin to read from the reader?
i.e. where do you call
Reader4.Read();
after
Reader4 = Command4.ExecuteReader();

Related

SQLite3 with Flask Insert only allowing 1 character

I'm using Flask and trying to insert names (text) into an SQLite3 DB. The DB has one table (guests) and one column (name). However, it will only accept 1 character during the insert; anything more is failing.
If I hardcode 'nm' as a value, it still fails, so I don't think it's the Html template. I can manually add a value of varying length to the DB with the 'DB Browser' app, so I'm really at a loss here. Here's a code snippet.
#app.route('/addrec', methods=['POST', 'GET'])
def addrec():
msg = "msg"
if request.method == 'POST':
try:
nm = request.form['nm']
with sqlite3.connect("database.db") as con:
cur = con.cursor()
cur.execute('''Insert into guests values (?)''', nm)
con.commit()
msg = "Record successfully added"
Second argument to cur.execute should be a tuple:
cur.execute('''Insert into guests values (?)''', (nm,))
Why? If, for example, you call that argument arg then arg[0] is the string value you require (nm): the first item in that tuple.
Otherwise (when passing nm instead of the tuple) it will read nm[0] which is the first character of the string nm.

System.data.Sqlite: Return number of affected rows no matter if Query or NonQuery is used

I'm using System.Data.SQLite ADO.NET provider for SQLite and the following Powershell code to execute queries (and nonqueries) against a Sqlite3 DB:
Function Invoke-SQLite ($DBFile,$Query) {
try {
Add-Type -Path ".\System.Data.SQLite.dll"
}
catch {
write-warning "Unable to load System.Data.SQLite.dll"
return
}
if (!$DBFile) {
throw "DB Not Found" R
Sleep 5
Exit
}
$conn = New-Object System.Data.SQLite.SQLiteConnection
$conn.ConnectionString="Data Source={0}" -f $DBFile
$conn.Open()
$cmd = $Conn.CreateCommand()
$cmd.CommandText = $Query
#$cmd.CommandTimeout = 10
$ds = New-Object system.Data.DataSet
$da = New-Object System.Data.SQLite.SQLiteDataAdapter($cmd)
[void]$da.fill($ds)
$cmd.Dispose()
$conn.Close()
write-host ("{0} Row(s) returned " -f ($ds.Tables[0].Rows|Measure-Object|Select -ExpandProperty Count))
return $ds.Tables[0]
}
The problem is: while it is trivial to know how many rows have been SELECTed in a query operation, the same is not true if the operation is an INSERT,DELETE or UPDATE (nonqueries)
I know I could use the ExecuteNonQuery method, but i need a generic wrapper which returns number of affected rows while being agnostic about the query it executed (as Invoke-SQLCmd would do, for example)
Is that possible?
Thanks!
A few comments before the answer:
System.data.Sqlite supports executing multiple SQL statements for one command, as long as the CommandText has each valid statements delimited by a semicolon (;). This means that there could be a mixture of queries and DML statements (i.e. INSERT, UPDATE, DELETE). The fact that you do not want to distinguish between the type of statement in $Query tells me that you are likely just passing statements blindly, so it could contain any combination of statements. Simply getting only one value (whether from a query or DML) seems too limiting.
Using a DataAdapter to fill a dataset just to get counts is inefficient. Instead, it may be better to just get a DataReader object and count the returned rows. This also allows a separate count for each query statement to be retrieved, something that gets obscured by using the DataAdapter object. (Perhaps enumerating all tables in the resultant dataset could get the same number, but I'm not certain that would always be equivalent.)
One good thing is that if you insist on using a DataAdapter, it will still execute DML statements (even though the expected result is query that returns rows). The dataset will not be changed (filled), but all statements in the command text will still affect changes in the database, so the following solution will still be useful.
Even if the code had works, I assume that the line which prints "{0} Rows returned" is meant to get a simple count, but $ds.Tables[0].Rows needs to be $ds.Tables[0].Rows.Count.
Notes about this particular solution:
The key is to call either of the sqlite SQL functions changes() or total_changes(). These can be retrieved using SQL: SELECT total_changes();. I recommend getting total_changes() before and after a command, then subtracting the difference. That will get changes for multiple statements executed by one command.
I'm not a PowerShell guru, so I tested everything in C#. Treat the code below more as pseudo code since it may need tweaking.
The code:
$conn = New-Object System.Data.SQLite.SQLiteConnection
try {
$conn.ConnectionString="Data Source={0}" -f $DBFile
$conn.Open()
$cmdCount = $Conn.CreateCommand()
$cmd = $Conn.CreateCommand()
try {
$cmdCount.CommandText = "SELECT total_changes();"
$beforeChanges = $cmdcount.ExecuteScalar()
$cmd.CommandText = $Query
$ds = New-Object System.Data.DataSet
$da = New-Object System.Data.SQLite.SQLiteDataAdapter($cmd)
$rows = 0
try {
[void]$da.fill($ds)
foreach ($tbl in $ds.Tables) {
$rows += $tbl.Rows.Count;
}
} catch {}
$afterChanges = $cmdcount.ExecuteScalar()
$DMLchanges = $afterChanges - $beforeChanges
$totalRowAndChanges = $rows + $DMLchanges
# $ds.Tables[0] may or may not be valid here.
# If query returned no data, no tables will exist.
} finally {
$cmdCount.Dispose()
$cmd.Dispose()
}
} finally {
$conn.Dispose()
}
Alternatively, you could eliminate the DataAdapter:
$cmd.CommandText = $Query
$rdr = $cmd.ExecuteReader()
$rows = 0
do {
while ($rdr.Read()) {
$rows++
}
} while ($rdr.NextResult())
$rdr.Close();

How to use SQLitePCL execute content of sql file

I'm trying to use SQLitePCL package to develop a simple UWP app that executes database commands (create-select-update-delete). I created a database sql file that contains some sqlite commands and I'm trying to execute them in my code:
Uri appUri = new Uri("ms-appx:///Assets/db.sql");
StorageFile sFile = StorageFile.GetFileFromApplicationUriAsync(appUri).AsTask().ConfigureAwait(false).GetAwaiter().GetResult();
string sSQL = FileIO.ReadTextAsync(sFile).AsTask().ConfigureAwait(false).GetAwaiter().GetResult();
ISQLiteStatement cnStatement = dbConnection.Prepare(sSQL);
cnStatement.Step();
But when I run the program, it only executes the first statement in the sql file which is CREATE command and exit without executing the rest of the commands. Here is the sample content of the sql file:
CREATE TABLE Superhero (
Type TEXT PRIMARY KEY,
Picture TEXT
);
INSERT INTO Superhero (
Type,
Picture
)
VALUES (
'batman',
'batman.ico'
);
Anyone knows if there is a way in SQLitePCL to execute a sql file?
Any help would be very much appreciated!
Thanks!
According to the description of sqlite3_prepare interface:
These routines only compile the first statement in zSql, so *pzTail is left pointing to what remains uncompiled.
So that it seems like only the first statement in the commands is actually executed. The remainder is silently ignored. Since every command is ended up with symbol ";", for a quick and simple solution, you may just split the sql commands into single statements and then execute one by one. For example:
string sSQL = FileIO.ReadTextAsync(sFile).AsTask().ConfigureAwait(false).GetAwaiter().GetResult();
var dbConnection = new SQLiteConnection("sun.db", SQLiteOpen.READWRITE);
//using (ISQLiteStatement cnStatement = dbConnection.Prepare(sSQL))
//{
// var result = cnStatement.Step();
//}
var statements = sSQL.Split(new[] { ';' });
foreach (string onestate in statements)
{
using (ISQLiteStatement cnStatement = dbConnection.Prepare(onestate))
{
var result = cnStatement.Step();
}
}
Otherwise, you may need to update the SQLitePCL Nuget package.

ASP.NET/VB date works on localhost but not remoteserver

I'm having alot of trouble trying to get the date from a DateTime picker to save to my database. It works fine when run from Localhost, but when running it on the public server it doesn't.
Originally i used the cDate function, plus also tried Convert.ToDateTime. But on the server it now gives me an error "String was not recognized as a valid DateTime."
I researched and found that its best to used the DateTime.TryParse function. After finding an example i changed it for my project and now im getting the error "Must declare the scalar variable "#articledate"."
When i debug the project, the value added into the "result1" DateTime is correct. But it still throws the error at ExecuteNonQuery?
If it makes a difference, the main server is hosted with GoDaddy, Localhost is my PC.
Any help or advice would be greatly appreciated.
cnSQL1 = New SqlConnection(MSSQL.cRemoteConnectionString)
cnSQL1.Open()
sSQL = "SELECT NewsID FROM News WHERE Season = #season AND Heading = #heading AND ArticleDate = #articledate AND Author = #author AND Club = #club AND State = #state AND AddedDate = #addeddate AND AddedBy = #addedby AND Release = #release"
Dim com1 As New SqlCommand(sSQL)
com1.Connection = cnSQL1
com1.Parameters.AddWithValue("#season", General.sSeason)
com1.Parameters.AddWithValue("#heading", General.UppercaseFirstLetter(txtHeading.Text))
Dim result1 As DateTime
com.Parameters.AddWithValue("#articledate", DateTime.TryParseExact(txtArticleDate.Text, "dd-MM-yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, result1))
'com1.Parameters.AddWithValue("#articledate", Convert.ToDateTime(txtArticleDate.Text))
com1.Parameters.AddWithValue("#author", txtAuthor.Text)
com1.Parameters.AddWithValue("#club", ddlClub.SelectedItem.Value)
com1.Parameters.AddWithValue("#state", dsState.Tables(0).Rows(0).Item(0))
com1.Parameters.AddWithValue("#addeddate", Date.Today)
com1.Parameters.AddWithValue("#addedby", Session("UserID"))
com1.Parameters.AddWithValue("#updatedate", Date.Today)
com1.Parameters.AddWithValue("#updateby", Session("UserID"))
com1.Parameters.AddWithValue("#release", s)
com1.ExecuteNonQuery()
The error "Must declare the scalar variable "#articledate" is caused by a typo. When you add the parameter you should use the SqlCommand variable named com1 not the variable com.
But after this you have a more critical error. All the TryParse methods return booleans. The converted date is written in the last parameter passed to TryParse.
In this way you are passing a boolean to AddWithValue and this method takes whatever you put in the value parameter. It has no way to know that you want a date, so it happily complies with your request.
You should do (Notice that the SqlCommand to use is com1 not com)
Dim result1 As DateTime
if DateTime.TryParseExact(txtArticleDate.Text, "dd-MM-yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, result1) Then
com1.Parameters.AddWithValue("#articledate", resul1)
Else
.....
In general it is better to avoid AddWithValue exactly because it takes whatever you pass to it. The preferred way is with
if DateTime.TryParseExact(txtArticleDate.Text, "dd-MM-yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, result1) Then
com1.Parameters.Add("#articledate", SqlDbType.Datetime).Value = result1
com1.Parameters.AddWithValue("#season", General.sSeason)
com1.Parameters.AddWithValue("#heading", General.UppercaseFirstLetter(txtHeading.Text))
com1.Parameters.AddWithValue("#author", txtAuthor.Text)
com1.Parameters.AddWithValue("#club", ddlClub.SelectedItem.Value)
com1.Parameters.AddWithValue("#state", dsState.Tables(0).Rows(0).Item(0))
com1.Parameters.AddWithValue("#addeddate", Date.Today)
com1.Parameters.AddWithValue("#addedby", Session("UserID"))
' This is not used by the query, commented out
' com1.Parameters.AddWithValue("#updatedate", Date.Today)
' This is not used by the query, commented out
' com1.Parameters.AddWithValue("#updateby", Session("UserID"))
com1.Parameters.AddWithValue("#release", s)
com1.ExecuteNonQuery()
Else
MessageBox.Show("Date is not valid")
End If
I have also removed two parameters that are not used in the query above (though they should not cause the error message above)

Getting documents of last 25 minutes with formula and lotusscript

In lotus I have a view with order documents.
I am building an agent to search for all orders which are modified in the last 25 minutes.
For this I have done code like:
strFormule = "Form=""Order"" & #Modified >= #Adjust(#Today;0;0;0;0;-25;0) & Deleted !=""J"""
Set ndcOrder = currentDB.Search( strFormule, Nothing, 0 )
If ndcOrder.Count <> 0 Then
Set doc = ndcOrder.GetFirstDocument
While Not doc Is Nothing
So if it is 11.00 then it need to take orders which are modified today from 10.35
But in the debugger I also get orders which where modified 2 hours earlier.
How is this possible?
I think it's might be because you're using #today which doesn't have a time element. Try #Now instead ?
In the past I used the LotusScript method GetModifiedDocuments which lets you specify a NotesDateTime object to retrieve any document modified since.
Your code could then look like this:
Dim session As New NotesSession
Dim db As NotesDatabase
Dim dc As notesdocumentcollection
Dim since As New NotesDateTime("")
Set db = session.CurrentDatabase
Call since.SetNow()
Call since.AdjustMinute(-25)
Set dc = db.GetModifiedDocuments(since)
My experience with this method was very good so far. More info on GetModifiedDocuments
Why use formula at all?
I would create a hidden view, first column is last modified date-time, sorted descending.
Then I would write my Lotusscript code to start at the top and work its way down until it encounters a date/time value that is older than 25 minutes ago.
Something like this:
Dim docs List As NotesDocument
Set dt25 = New NotesDateEntry(Now())
Call dt25.AdjustMinutes(-25)
Dim col as NotesViewEntryCollection
Dim entry as NotesViewEntry
Set col = view.AllEntries
Set entry = col.GetFirstEntry
Do Until entry Is Nothing
If Cdat(entry.ColumnValues(0))<Cdat(dt25.LSLocalTime) Then
Exit Loop
End If
Set docs(entry.Document.UniversalID) = entry.Document
Loop
' Now you have a list of documents created in the last 25 minutes.

Resources