System.Data.Sqlite problems - c#

I'm having a problem getting Sqlite to work in my c# irc bot.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SQLite;
using System.IO;
namespace ModBot
{
class Database
{
private SQLiteConnection myDB;
private SQLiteCommand cmd;
public Database()
{
InitializeDB();
}
private void InitializeDB()
{
if (File.Exists("ModBot.db"))
{
Console.WriteLine("HEYOOOOOOO");
myDB = new SQLiteConnection("Data Source=ModBot.db;Version=3;");
String sql = "CREATE TABLE IF NOT EXISTS twitch (id INTEGER PRIMARY KEY, user TEXT, currency INTEGER DEFAULT 0, subscriber INTEGER DEFAULT 0, btag TEXT DEFAULT null);";
cmd = new SQLiteCommand(sql, myDB);
cmd.ExecuteNonQuery();
}
else
{
Console.WriteLine("YOOHOOOOO");
SQLiteConnection.CreateFile("ModBot.db");
myDB = new SQLiteConnection("Data Source=ModBot.db;Version=3;");
String sql = "CREATE TABLE IF NOT EXISTS twitch (id INTEGER PRIMARY KEY, user TEXT, currency INTEGER DEFAULT 0, subscriber INTEGER DEFAULT 0, btag TEXT DEFAULT null);";
cmd = new SQLiteCommand(sql, myDB);
cmd.ExecuteNonQuery();
}
}
}
}
I downloaded System.Data.Sqlite, and added it as a resource to my project. When I run the code, it throws a DllNotFound exception (Specifically: Unable to load DLL 'SQLite.Interop.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)) when it tries to make the actual connection.
Any ideas?

Installing the RTM version of the Visual C++ runtime libraries works perfectly with System.Data.SQLite 1.0.74. So the SP1 version is not needed.
The version of the C runtime installed with the .NET 4 runtime is the RTM version of msvcr100, but has the name msvcr100_clr0400.dll. With a copy of this renamed to msvcr100.dll, either in System32 or next to the System.Data.SQLite.dll, everything seems to work.
It seems they've moved away from SxS deployment of the C runtime. So no more 'dependency' tag in the embedded manifest, and whatever the latest version is in System32 (or same directory as the .exe) will be loaded.
Some buddy asked a question on StackOverflow about these changes: Visual C++ 2010: Changes to MSVC runtime deployment (no more SxS with manifest).
This all means for the .NET 4 version you can deploy System.Data.SQLite.dll and msvcr100.dll in the same directory, which was not possible with the previous version of the runtime. For me that sorts out all my problems and you can move to the current versions of System.Data.SQLite.dll.

Related

.Net Core - SQL Server Geography data type exception

I am trying to use the new Microsoft.Data.SqlClient in my .Net Core application. Whenever I select a column that has a datatype of Geography, I get the following error.
Unable to cast object of type 'Microsoft.SqlServer.Types.SqlGeography' to type 'Microsoft.Data.SqlClient.Server.IBinarySerialize'.'
To reproduce, I created a database on my computer (SQL2019) with one table:
DROP TABLE IF EXISTS geotest
GO
CREATE TABLE geotest (g GEOGRAPHY)
GO
INSERT INTO geotest (g)
VALUES
( 0xe6100000010cec51b81e854b4040ec51b81e852b58c0 ),
( 0xe6100000010c6666666666a64740713d0ad7a3905ec0 )
I create a console application project (Visual Studio 2019, .Net Core 3.1) and add the NUGET package: Microsoft.Data.SqlClient
Here is my sample app:
using System;
using Microsoft.Data.SqlClient;
namespace TestWithOtherSQL
{
class Program
{
static void Main(string[] args)
{
SqlConnection conn = new SqlConnection("Data Source=localhost;Initial Catalog=joe;Trusted_Connection=True;");
conn.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = #"SELECT g FROM geotest";
SqlDataReader sr = cmd.ExecuteReader();
while (sr.Read())
{
var a = sr[0];
}
conn.Close();
Console.WriteLine("Hello World!");
}
}
}
It throws the error on this line:
var a = sr[0];
Unable to cast object of type 'Microsoft.SqlServer.Types.SqlGeography' to type 'Microsoft.Data.SqlClient.Server.IBinarySerialize'.'
Troubleshooting:
If I change out the Nuget package to System.Data.SqlClient and include package Microsoft.SqlServer.Types (change the using to System.Data.SqlClient) The same code works.
So why don't I just do that? Good question... My actual database is on Azure SQL DB and I need to use Microsoft.Data.SqlClient to support ActiveDirectory Password Authentication (that does not work with System.Data.SqlClient) - but that's a different issue....
Also Microsoft.Data.SqlClient is the "new" ".NetCore" way of doing things. Not a huge issue for me right now, but not sure if that would work if we ported to Linux are tried to run in an Azure function.

BadImageFormatException with SQLite in ASP.NET razor website

I'm trying to create a very simple webshop in Razor with SQLite. Unfortunately, when i trying to create the database (or creating the SQLiteConnection object) it throws a strange System.BadImageFormatException.
An attempt was made to load a program with an incorrect format.
(Exception from HRESULT: 0x8007000B)"} System.BadImageFormatException
My code looks similar as the following:
public bool CreateDatabase()
{
try
{
string db = HttpContext.Current.Server.MapPath("~/App_Data/mydb.sqlite");
SQLiteConnection.CreateFile(db);
SQLiteConnection m_dbConnection = new SQLiteConnection(#"Data Source="+ db + ";Version=3;");
m_dbConnection.Open();
string sql = "create TABLE cart (UserHash varchar(35), imageid varchar(255), rider varchar(255), competition varchar(255), usagetype varchar(255), retouch varchar(10), blacknwhite varchar(10))";
SQLiteCommand command = new SQLiteCommand(sql, m_dbConnection);
command.ExecuteNonQuery();
return true;
}
catch (Exception)
{
return false;
}
}
This website probably will run on third-party hosting, so it's essential to use a relative path for the sqlite file location, although i couldn't get it work so far.
In db variable, i get the correct App_Data folder location.
I get the exception at new SQLiteConnection. I also tried using the following connectionstring, no luck:
"Data Source=|DataDirectory|mydb.sqlite; Version=3;"
What am i missing?
BadImageFormatException happens when your application and your libraries use a different bitness. For example, the application is built for AnyCPU (without prefer 32bit) or x64 and your libraries are compiled for 32bit or viceversa.
Usually the solution is very simple. Just copy the appropriate version of SQLite for the bitness of your app to your run folder or change the Target Platform of your app to match the library version used

Data missing from Access database after added using textboxes [duplicate]

I have following C# code in a console application.
Whenever I debug the application and run the query1 (which inserts a new value into the database) and then run query2 (which displays all the entries in the database), I can see the new entry I inserted clearly. However, when I close the application and check the table in the database (in Visual Studio), it is gone. I have no idea why it is not saving.
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlServerCe;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
try
{
string fileName = "FlowerShop.sdf";
string fileLocation = "|DataDirectory|\\";
DatabaseAccess dbAccess = new DatabaseAccess();
dbAccess.Connect(fileName, fileLocation);
Console.WriteLine("Connected to the following database:\n"+fileLocation + fileName+"\n");
string query = "Insert into Products(Name, UnitPrice, UnitsInStock) values('NewItem', 500, 90)";
string res = dbAccess.ExecuteQuery(query);
Console.WriteLine(res);
string query2 = "Select * from Products";
string res2 = dbAccess.QueryData(query2);
Console.WriteLine(res2);
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e);
Console.ReadLine();
}
}
}
class DatabaseAccess
{
private SqlCeConnection _connection;
public void Connect(string fileName, string fileLocation)
{
Connect(#"Data Source=" + fileLocation + fileName);
}
public void Connect(string connectionString)
{
_connection = new SqlCeConnection(connectionString);
}
public string QueryData(string query)
{
_connection.Open();
using (SqlCeDataAdapter da = new SqlCeDataAdapter(query, _connection))
using (DataSet ds = new DataSet("Data Set"))
{
da.Fill(ds);
_connection.Close();
return ds.Tables[0].ToReadableString(); // a extension method I created
}
}
public string ExecuteQuery(string query)
{
_connection.Open();
using (SqlCeCommand c = new SqlCeCommand(query, _connection))
{
int r = c.ExecuteNonQuery();
_connection.Close();
return r.ToString();
}
}
}
EDIT: Forgot to mention that I am using SQL Server Compact Edition 4 and VS2012 Express.
It is a quite common problem. You use the |DataDirectory| substitution string. This means that, while debugging your app in the Visual Studio environment, the database used by your application is located in the subfolder BIN\DEBUG folder (or x86 variant) of your project. And this works well as you don't have any kind of error connecting to the database and making update operations.
But then, you exit the debug session and you look at your database through the Visual Studio Server Explorer (or any other suitable tool). This window has a different connection string (probably pointing to the copy of your database in the project folder). You search your tables and you don't see the changes.
Then the problem get worse. You restart VS to go hunting for the bug in your app, but you have your database file listed between your project files and the property Copy to Output directory is set to Copy Always. At this point Visual Studio obliges and copies the original database file from the project folder to the output folder (BIN\DEBUG) and thus your previous changes are lost.
Now, your application inserts/updates again the target table, you again can't find any error in your code and restart the loop again until you decide to post or search on StackOverflow.
You could stop this problem by clicking on the database file listed in your Solution Explorer and changing the property Copy To Output Directory to Copy If Newer or Never Copy. Also you could update your connectionstring in the Server Explorer to look at the working copy of your database or create a second connection. The first one still points to the database in the project folder while the second one points to the database in the BIN\DEBUG folder. In this way you could keep the original database ready for deployment purposes and schema changes, while, with the second connection you could look at the effective results of your coding efforts.
EDIT Special warning for MS-Access database users. The simple act of looking at your table changes the modified date of your database ALSO if you don't write or change anything. So the flag Copy if Newer kicks in and the database file is copied to the output directory. With Access better use Copy Never.
Committing changes / saving changes across debug sessions is a familiar topic in SQL CE forums. It is something that trips up quite a few people. I'll post links to source articles below, but I wanted to paste the answer that seems to get the best results to the most people:
You have several options to change this behavior. If your sdf file is part of the content of your project, this will affect how data is persisted. Remember that when you debug, all output of your project (including the sdf) if in the bin/debug folder.
You can decide not to include the sdf file as part of your project and manage the file location runtime.
If you are using "copy if newer", and project changes you make to the database will overwrite any runtime/debug changes.
If you are using "Do not copy", you will have to specify the location in code (as two levels above where your program is running).
If you have "Copy always", any changes made during runtime will always be overwritten
Answer Source
Here is a link to some further discussion and how to documentation.

Saving data in a Database C# WPF [duplicate]

I have following C# code in a console application.
Whenever I debug the application and run the query1 (which inserts a new value into the database) and then run query2 (which displays all the entries in the database), I can see the new entry I inserted clearly. However, when I close the application and check the table in the database (in Visual Studio), it is gone. I have no idea why it is not saving.
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlServerCe;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
try
{
string fileName = "FlowerShop.sdf";
string fileLocation = "|DataDirectory|\\";
DatabaseAccess dbAccess = new DatabaseAccess();
dbAccess.Connect(fileName, fileLocation);
Console.WriteLine("Connected to the following database:\n"+fileLocation + fileName+"\n");
string query = "Insert into Products(Name, UnitPrice, UnitsInStock) values('NewItem', 500, 90)";
string res = dbAccess.ExecuteQuery(query);
Console.WriteLine(res);
string query2 = "Select * from Products";
string res2 = dbAccess.QueryData(query2);
Console.WriteLine(res2);
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e);
Console.ReadLine();
}
}
}
class DatabaseAccess
{
private SqlCeConnection _connection;
public void Connect(string fileName, string fileLocation)
{
Connect(#"Data Source=" + fileLocation + fileName);
}
public void Connect(string connectionString)
{
_connection = new SqlCeConnection(connectionString);
}
public string QueryData(string query)
{
_connection.Open();
using (SqlCeDataAdapter da = new SqlCeDataAdapter(query, _connection))
using (DataSet ds = new DataSet("Data Set"))
{
da.Fill(ds);
_connection.Close();
return ds.Tables[0].ToReadableString(); // a extension method I created
}
}
public string ExecuteQuery(string query)
{
_connection.Open();
using (SqlCeCommand c = new SqlCeCommand(query, _connection))
{
int r = c.ExecuteNonQuery();
_connection.Close();
return r.ToString();
}
}
}
EDIT: Forgot to mention that I am using SQL Server Compact Edition 4 and VS2012 Express.
It is a quite common problem. You use the |DataDirectory| substitution string. This means that, while debugging your app in the Visual Studio environment, the database used by your application is located in the subfolder BIN\DEBUG folder (or x86 variant) of your project. And this works well as you don't have any kind of error connecting to the database and making update operations.
But then, you exit the debug session and you look at your database through the Visual Studio Server Explorer (or any other suitable tool). This window has a different connection string (probably pointing to the copy of your database in the project folder). You search your tables and you don't see the changes.
Then the problem get worse. You restart VS to go hunting for the bug in your app, but you have your database file listed between your project files and the property Copy to Output directory is set to Copy Always. At this point Visual Studio obliges and copies the original database file from the project folder to the output folder (BIN\DEBUG) and thus your previous changes are lost.
Now, your application inserts/updates again the target table, you again can't find any error in your code and restart the loop again until you decide to post or search on StackOverflow.
You could stop this problem by clicking on the database file listed in your Solution Explorer and changing the property Copy To Output Directory to Copy If Newer or Never Copy. Also you could update your connectionstring in the Server Explorer to look at the working copy of your database or create a second connection. The first one still points to the database in the project folder while the second one points to the database in the BIN\DEBUG folder. In this way you could keep the original database ready for deployment purposes and schema changes, while, with the second connection you could look at the effective results of your coding efforts.
EDIT Special warning for MS-Access database users. The simple act of looking at your table changes the modified date of your database ALSO if you don't write or change anything. So the flag Copy if Newer kicks in and the database file is copied to the output directory. With Access better use Copy Never.
Committing changes / saving changes across debug sessions is a familiar topic in SQL CE forums. It is something that trips up quite a few people. I'll post links to source articles below, but I wanted to paste the answer that seems to get the best results to the most people:
You have several options to change this behavior. If your sdf file is part of the content of your project, this will affect how data is persisted. Remember that when you debug, all output of your project (including the sdf) if in the bin/debug folder.
You can decide not to include the sdf file as part of your project and manage the file location runtime.
If you are using "copy if newer", and project changes you make to the database will overwrite any runtime/debug changes.
If you are using "Do not copy", you will have to specify the location in code (as two levels above where your program is running).
If you have "Copy always", any changes made during runtime will always be overwritten
Answer Source
Here is a link to some further discussion and how to documentation.

Mono can't open sqlite database

I'm attempting to do a very basic connection to a sqlite v3 database and I'm using monodevelop 3.0 and Mono 2.10 and am unable to get connected to the database. I can make the app create the database, but then it immediately fails attempting to connect to it. Any suggestions? I had started with a different database, but then decided to have my app attempt to create a database empty and then connect to it. This still seems to fail.
SqliteConnection.CreateFile("db\\DataWorksProg.s3db");
SqliteConnection conn = new SqliteConnection("Data Source=file:db\\DataWorksProg.s3db");
conn.Open();
This small piece of code fails with an error about not being able to open the database file.
Mono.Data.Sqlite.SqliteException: Unable to open the database file
Permissions look OK and I have the Sqlite3.dll in the project, and it seems to be working OK. Have I missed anything obvious? I'm pretty good on the Visual Studio side, but still fairly fresh working in a Mono/Monodevelop environment.
What platform?
I don't believe you need to create a file. If it's not found, iirc, it'll make the database file.
Fwiw, on a Mac, I'm doing (note URI to a pretty standard path; I haven't used Data Source)...
using System;
using System.Data;
using Mono.Data.Sqlite;
namespace test
{
class MainClass
{
public static void Main (string[] args)
{
IDbConnection conTemp = null;
IDbCommand cmdTemp = null;
conTemp = (IDbConnection)new SqliteConnection ("URI=file:/Users/userName/mnmh.db");
conTemp.Open ();
cmdTemp = conTemp.CreateCommand ();
cmdTemp.CommandText = "SELECT * FROM employee";
IDataReader drTemp = cmdTemp.ExecuteReader ();
while (drTemp.Read()) {
Console.WriteLine (drTemp.GetString (0));
}
}
}
}
etc etc
Check the obvious -- you've referenced all the stuff you're using, etc.
Figured out my problem here. Apparently instead of using
"Data Source=file:db\\DataWorksProg.s3db"
I should have been using
"URI=file:db\\DataWorksProg.s3db"
Switched to the URI and it works as expected. I had thought from reading the docs that under the 2.0 profile, the DataSource part was needed instead of the URI, but I got the results I'm looking for.

Categories

Resources