IBM Informix ODBC driver C# - The cursor has been previously released and is unavailable - odbc

Trying to switch database using Database (database name); query and then execute a query on that database in two separate queries.
However, I got this error: The cursor has been previously released and is unavailable. What does this mean?
Here is the code:
using (OdbcCommand command = new OdbcCommand(null, odbcConnection))
{
if (switchDBName != null)
{
command.CommandText = "Database " + switchDBName + ";";
command.ExecuteNonQuery();
Console.WriteLine("Switched to database: " + switchDBName + " Successfully.");
}
command.CommandTimeout = 0;
command.CommandText = query;
using (OdbcDataReader datareader = command.ExecuteReader())
{
DataTable resultDT = new DataTable();
resultDT.Load(datareader);
Console.WriteLine("ExecuteODBCQuery -- Finished. There are " + resultDT.Rows.Count + " rows.");
return resultDT;
}
}

If I'm following the logic correctly:
you have two different database connections;
you create a cursor-based statement using one connection;
you switch to the other database connection;
you get an error indicating that the cursor is not available on the current connection
albeit with not wholly appropriate wording in the error message.
A prepared statement or a cursor-based statement is associated with a connection. The same statement will not work for another connection; you have to recreate the cursor or prepared statement for each database connection.
You must know which connection was used for each prepared statement or cursor-based statement. You can switch connections between uses, but when you try to use a statement, the connection must be the same as was in use when it was prepared.

Related

In asp.net with sqlite set pragma Synchronous=Off

Try optimize Sqlite in an asp.net app by setting Synchronous=Off in the connection string, but keyword isn't supported https://github.com/ericsink/SQLitePCL.raw/issues/147
https://github.com/aspnet/Microsoft.Data.Sqlite/issues/354
Bottom of issue #354 suggests a solution with a pragma command towards the connection
using (var command = connection.CreateCommand())
{
command.CommandText = "PRAGMA foreign_keys = true;";
command.ExecuteNonQuery();
}
Try to use this for Synchronous
https://sqlite.org/pragma.html#pragma_synchronous but uncertain where/how to obtain the correct connection corresponding to my DbContext type.
Drop down to the ADO.NET connection in EF Core using code like this:
db.Database.OpenConnection();
try
{
var connection = db.Database.GetDbConnection();
// TODO: Use connection
}
finally
{
db.Database.CloseConnection();
}

Show sqlite database in Delphi XE6 using firedac programmatically

I am new in database using Delphi. Actually I need to display all the tables and their data in a gridview using firedac. Several videos on youtube and docwiki teaches how to access database through visual components i.e. throwing FDConnetion, FDTable, DataSource, etc. on the form.
But I would like to do the same thing programmatically so that I can focus more on coding and separate form from the business logic.
Here is what I have done in C# while accessing MSAccess data:
public void LoadUsersInfo()
{
try {
OleDbConnection Connection = new OleDbConnection();
Connection.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;DataSource=dbCyberNet.accdb;Persist Security Info=False;";
Connection.Open();
OleDbCommand command = new OleDbCommand();
command.Connection = Connection;
String query = "SELECT * FROM tblUsersInfo";
command.CommandText = query;
OleDbDataAdapter adapter = new OleDbDataAdapter(command);
DataTable dt = new DataTable();
adapter.Fill(dt);
dbGrid.DataSource = dt;
}
catch (Exception ex) {
MessageBox.Show("Error occured while loading users information . " + ex.Message.ToString());
}
finally { Connection.Close(); }
}
I would like to do similar in delphi for sqlite database. Here is what I have tried (edited).
procedure TForm1.Button1Click(Sender: TObject);
var
con: TFDConnection;
table: TFDTable;
ds: TDataSource;
begin
con := TFDConnection.Create(nil);
con.LoginPrompt := False;
table := TFDTable.Create(nil);
table.TableName := 'Students';
ds := TDataSource.Create(nil);
ds.DataSet := table;
try
con.Open('DriverID=SQLite;Database=‪studentsDB.sqlite;');
table.Connection := con;
table.Active := True;
con.Connected := True;
DBGrid1.DataSource := ds;
finally
con.Close;
con.Free;
table.Free;
ds.Free;
end;
end;
Whenever I run this code, error dialog appears showing: First chance exception at $759AF097. Exception class ESQLiteNativeException with message '[FireDAC][Phys][SQLite] ERROR: no such table: STUDENTS'. Process Project1.exe (3836)
whereas the same table name exists inside the table and using visual firedac components, I can see the data grid fills easily.
You can do the same as with C#: assign your TFDQuery instance as DataSource of the VCL grid!
Add a TDataSource to the form, set its DataSet property to your TFDQuery, and assign it to your grid.
See the official Delphi documentation and other SO questions.
You can execute your Select query by calling the query's Open method so your code will look like this :-
procedure TStudents.executeQuery;
var
con: TFDConnection;
query: TFDQuery;
begin
con := TFDConnection.Create(nil);
query := TFDQuery.Create(con);
con.LoginPrompt := False;
con.Open('DriverID=SQLite;Database=studentsDB.sqlite;');
query.Connection := con;
query.SQL.Text := 'SELECT * FROM Students';
query.Open;
query.First;
While Not Query.EOF Do
Begin
// Populate your object or do whatever processing you like here.
Query.Next;
End;
end;
You can then programatically create a TDataSource and a Grid and hook those up in code in a similar fashion. You'll need to move the Connection and Query objects out of your object's executeQuery method as they are local variables and will not be accessible to anything outside that method.
Note that Delphi does not garbage collect like C# does, so as it stand, the code leaks memory.
As an aside, your code appears to be an object method and it looks like you're attempting to create a set of business objects that know how to load and save themselves. Rather than roll your own, you might be better served by looking at one of the existing frameworks that exist (tiOPF, InstantObjects, mORMot or TMS Aurelius) to achieve this. These will allow you to concentrate on solving the problem at hand and not worry about the minutae of creating, loading and saving of objects.

ASP.NET SqlBulkCopy does not insert all records on server

I don't have any idea why SqlBulkCopy does not insert all of the records from the reader. Code:
using (OleDbDataReader dr1 = cmd.ExecuteReader())
{
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(ss, SqlBulkCopyOptions.TableLock, null))
{
bulkCopy.BulkCopyTimeout = 0;
bulkCopy.BatchSize = 500;
bulkCopy.DestinationTableName = tableName;
try
{
bulkCopy.WriteToServer(dr1);
}
catch (Exception ex)
{
Log.LogSystemLog(ex.ToString());
return false;
}
}
GC.Collect();
dr1.Close();
}
I want to bulkCopy about 300k records. It works when I'm running this from localhost to the same database, but when I run this from the server - it always inserts ~7k records... and no error, or exception. On the server 4GB free RAM are available. On localhost ~ 1,5GB.
I have no idea why it's working properly on localhost, but on the server it is not.
I had the same problem, solved by adding the following to my connection string.
IMEX=1
Example:
string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + Server.MapPath(rutacom) + ";" + "Extended Properties='Excel 12.0 Xml; HDR=YES; IMEX=1'";
In my localhost was working perfectly, but not on server.
Try it :)
Notes:
"HDR=Yes;" indicates that the first row contains columnnames, not data. "HDR=No;" indicates the opposite.
To always use IMEX=1 is a safer way to retrieve data for mixed data columns. Consider the scenario that one Excel file might work fine cause that file's data causes the driver to guess one data type while another file, containing other data, causes the driver to guess another data type. This can cause your app to crash.

MySQL Data Access Layer: How do you store your queries?

I've been building this project as the solo dev for a while, and while I'm comfortable in the front end and middle tier, I don't really think I'm doing the database the way I should be, and the reason why is because I simply don't really know of any other way. The way I'm currently getting data is by testing out queries in my MySQL workbench and copying and pasting the SQL as a string literal into a method that makes a call to the DB, pulls the data and hydrates my objects.
This hasn't really been a problem until recently, when I had to create a monster of a query and it got me thinking that maybe there's a better way to do this. I don't have a formal DAL separated out, so I know there's room for improvement there, but I was curious about what the correct way would be to store SQL strings. I assume there is a tool somewhere built into VS10 where I can manipulate and work with SQL as SQL instead of as a string.
You should be doing this in stored procedures. That will basically format and store your query. You set parameters that are passed in from your code, then read out the results.
Example:
The C# method:
private void SetNote()
{
const string sql = "sp_SelectControllerNoteByID";
using (var conn = MocSystem.GetMocDbConnection())
{
using (var comm = new SqlCommand(sql, conn))
{
comm.CommandType = CommandType.StoredProcedure;
comm.Parameters.Add(new SqlParameter("#ControllerNoteID", ControllerNoteId));
try
{
conn.Open();
using (var rdr = comm.ExecuteReader())
{
while (rdr.Read())
{
CommentText = rdr["NoteText"].ToString();
_commentor = new User(new Guid(rdr["NoteAuthor"].ToString()));
CommentDate = (DateTime)rdr["NoteDate"];
MocRequestId = (int)rdr["MocRequestID"];
}
}
}
catch (Exception ex)
{
HasError = true;
ErrorMessage += "\nThere was a problem building the note: " + ex.Message;
}
}
}
}
The stored procedure on the DBMS (sql server in this example):
ALTER proc [dbo].[sp_SelectControllerNoteByID]
#ControllerNoteID int
AS
SELECT
ControllerNoteID,
NoteText,
NoteDate,
NoteAuthor,
MocRequestID
FROM
ControllerNotes
WHERE
ControllerNoteID = #ControllerNoteID
So here we call the stored procedure which in this case is just a simple select statement, then we read it out into an object via ADO. Now, this way, you can modify your query without recompiling. Unless you add parameters, in which case you'll have to update those in your code as well.

Simplest way to access a DB2 database on iSeries from a Linux (ubuntu) machine?

I would like to run an SQL query on an iSeries (...or "System i" or "AS/400"...) machine as part of a Nagios check, but haven't found a suitable way of interfacing the database yet.
IBM suggests using the ODBC driver of System i Access for Linux with unixODBC, but since both systems are new to me, I'd like to know if there are other ways of doing this.
Hacks involving telnet and expect are perfectly fine. :-)
I think this would be the simplest ...
Same as Access for Linux but it is the open source version: JTOpen
example taken from iSeries Information Center:
// Connect to the server.
Connection c = DriverManager.getConnection("jdbc:as400://mySystem");
// Create a Statement object.
Statement s = c.createStatement();
// Run an SQL statement that creates
// a table in the database.
s.executeUpdate("CREATE TABLE MYLIBRARY.MYTABLE (NAME VARCHAR(20), ID INTEGER)");
// Run an SQL statement that inserts
// a record into the table.
s.executeUpdate("INSERT INTO MYLIBRARY.MYTABLE (NAME, ID) VALUES ('DAVE', 123)");
// Run an SQL statement that inserts
// a record into the table.
s.executeUpdate("INSERT INTO MYLIBRARY.MYTABLE (NAME, ID) VALUES ('CINDY', 456)");
// Run an SQL query on the table.
ResultSet rs = s.executeQuery("SELECT * FROM MYLIBRARY.MYTABLE");
// Close the Statement and the
// Connection.
s.close();
c.close();
Found at Nagios Exchange:
DB2 Checker
Download DB2 Checker
untested...
I had this source on my disk. It's a good example. For clarity, I did change the machine, catalog and table name in the source. Hope it helps. It uses the JDBC driver from the JTOpen project.
Notice that with this specific driver you can access the iSeries DB2 database as any other database. Also, the DB2 database on the iSeries is just one of the versions of the IBM Universal Database. However, you can do iSeries specific tricks, even with the JDBC driver. But if you want to stay SQL defaults only, that is fine too.
import java.sql.*;
public class TestSQL {
public static void main(String[] args) {
try {
DriverManager
.registerDriver(new com.ibm.as400.access.AS400JDBCDriver());
Connection conn = DriverManager
.getConnection("jdbc:as400://YOURISERIES/YOURLIBRARY");
Statement select = conn.createStatement();
ResultSet rs = select.executeQuery("select * from whatever");
ResultSetMetaData rsmd = rs.getMetaData();
while (rs.next()) {
for (int x=1; x <= rsmd.getColumnCount(); x++) {
System.out.print(rs.getString(x));
}
System.out.println();
}
} catch (Exception e) {
System.out.println("error: " + e.getMessage());
}
System.exit(0);
}
}

Resources