Hello i'm working on an android game project in unity3d 5 (language c#)that needs to save some data to sqlite database.
the game doesn't have a lot of data to store it has only 1 table .there are some plugins for unity that connect to sqlite but i don't want to use them .
so how can i store my data on sqlite file in unity ?
You can find your answer here
Create new folder under Assets Folder Rename it Plugins .
Copy sqlite3.def and sqlite3.dll into Assets/Plugins in your unity project .You can download these files here
http://www.sqlite.org/download.html for windows (Precompiled Binaries
for Windows)
Download SQLite Browser http://sourceforge.net/projects/sqlitebrowser/ or
http://sqliteadmin.orbmu2k.de/ download SQLite Administrator tool
Create Database in Assets folder in your unity project using SQLite Browser.
Copy System.Data.dll and Mono.Data.Sqlite.dll from **C:\Program Files (x86)\Unity \Editor\Data\Mono\lib\mono\2.0* and paste them in your Assets/Plugins* folder in your unity project.
Add these namespaces using Mono.Data.Sqlite; using System.Data; using System;
string conn= "URI=file:" + Application.dataPath + "/PickAndPlaceDatabase.s3db";
Replace PickAndPlaceDatabase.s3db with your database name
void Start () {
string conn = "URI=file:" + Application.dataPath + "/PickAndPlaceDatabase.s3db"; //Path to database.
IDbConnection dbconn;
dbconn = (IDbConnection) new SqliteConnection(conn);
dbconn.Open(); //Open connection to the database.
IDbCommand dbcmd = dbconn.CreateCommand();
string sqlQuery = "SELECT value,name, randomSequence " + "FROM PlaceSequence";
dbcmd.CommandText = sqlQuery;
IDataReader reader = dbcmd.ExecuteReader();
while (reader.Read())
{
int value = reader.GetInt32(0);
string name = reader.GetString(1);
int rand = reader.GetInt32(2);
Debug.Log( "value= "+value+" name ="+name+" random ="+ rand);
}
reader.Close();
reader = null;
dbcmd.Dispose();
dbcmd = null;
dbconn.Close();
dbconn = null;
}
Further SQLite Help Visit : http://www.tutorialspoint.com/sqlite/
Related
I have few thousands attachments saved in a SQL Server database with column datatype varbinary(max). I want to retrieve all these files and save them to a local drive.
What is the best way to achieve that? I am not looking for code specifically but trying to understand all options so I can do this in C#.
Suggestions are appreciated. Thank you
You can do any of the followings:
Write a SQL script which will read the data from the table and save those to the disk. Here is how that can be done
You can write a C# script which will connect to the Database, Read and store the data as a file to a disk
Use the Id of the table as part of the file name to make it unique if you are storing all the files to a single folder.
Here's example code.
Note, the namespace System.Data.SqlClient is not referenced by a .NET Core project by default as done by .NET Framework; you have to manually add the System.Data.SqlClient NuGet package to the project.
using System.Data.SqlClient;
var connectionString = "Data Source=localhost;Initial Catalog=MyDatbase;Integrated Security=True;";
var outputFolder = #"C:\temp\";
using var conn = new SqlConnection(connectionString);
conn.Open();
var query = "select DocumentId, Contents from DocumentFile where ID >= 1234";
using var cmd = new SqlCommand(query);
cmd.Connection = conn;
var reader = cmd.ExecuteReader();
if (!reader.HasRows) throw new Exception("No rows!");
while (reader.Read())
{
var fileName = $"{reader["DocumentId"]}.pdf";
var data = (byte[])reader["Contents"];
if (data == null) throw new Exception("Contents is null");
using var writer = new BinaryWriter(File.OpenWrite(Path.Combine(outputFolder, fileName)));
writer.Write(data);
}
Background information
My game is working on iOS, and now trying to update it to work on android. I have a database, Artifact.db, in a StreamingAssets folder, that is built off of SQLite and that has read-only information that I use to get data for the game.
Issue
The core issue is that the SQlite can't read the data, most likely because its not accessible from what I have been reading through on the docs. I am looking for any solutions but preferably something using the UnityWebRequest feature rather than the deprecated WWW
Working iOS Code
// Platform dependent code
string filepath = Application.streamingAssetsPath + "/Artifact.db";
string conn = "URI=file:" + filepath;
// SQlite
IDbConnection dbconn;
IDbCommand dbcmd;
IDataReader reader;
dbconn = (IDbConnection)new SqliteConnection(conn);
dbconn.Open();
dbcmd = dbconn.CreateCommand();
string sqlQuery = $"SELECT * FROM Artifact WHERE Rarity='{type}'";
dbcmd.CommandText = sqlQuery;
reader = dbcmd.ExecuteReader();
Using this code above on android results in error when doing the reader = dbcmd.ExecuteReader(); since it cannot find file.
Attempts at Android code
(Since the SQLite code itself is fine I'll only be including the platform-dependent section which deals with finding the file.)
string DatabaseName = "Artifact.db";
#if UNITY_ANDROID
string filepath = Application.persistentDataPath + "/Artifact.db";
if (!File.Exists(filepath))
{
Debug.Log("Database not in Persistent path");
// if it doesn't ->
// open StreamingAssets directory and load the db ->
var loadDb = new WWW("jar:file://" + Application.dataPath + "!/assets/" + DatabaseName); // this is the path to your StreamingAssets in android
while (!loadDb.isDone) { } // CAREFUL here, for safety reasons you shouldn't let this while loop unattended, place a timer and error check
// then save to Application.persistentDataPath
File.WriteAllBytes(filepath, loadDb.bytes);
}
string conn = "URI=file:" + filepath;
#endif
I also tried the code from this unity forum post. (also modified some things to fit my project)
var loadingRequest = UnityWebRequest.Get(Path.Combine(Application.streamingAssetsPath, "Artifact.db"));
// Used "Artifact.db" instead of "your.bytes"
loadingRequest.SendWebRequest();
while (!loadingRequest.isDone) {
if (loadingRequest.isNetworkError || loadingRequest.isHttpError) {
break;
}
}
if (loadingRequest.isNetworkError || loadingRequest.isHttpError) {
} else {
File.WriteAllBytes(Path.Combine(Application.persistentDataPath , "Artifact.db"), loadingRequest.downloadHandler.data);
// Used "Artifact.db" instead of "your.bytes"
}
string filepath = Application.persistentDataPath + "/Artifact.db";
string conn = "URI=file:" + filepath;
What I am hoping for
I ideally hope to replicate the iOS code. I think this might mean copying the Artifact.db file to somewhere that is persistent and accessible on android and then using that file location to open the file with SQLite.
When I run my project in the Unity Editor, I can run my database. I can read and write to it with no issues. However when I build my project and run it, at the point where my database is read nothing happens.
I have set it up to create a text file when the database is read to check if it is read, but the text file is not created. From this I can assume that the database connection wasn't opened.
I am using a MySQL database that is in LocalHost.
Is there a way of putting a database in the project files so that is accessible wherever the program is (e.g. on another computer), and to make this database readable? As if it were a textfile. This would be all I need. The database has a number of tables and all of them are accesed from my C# scripts when the game is running.
I do have a password for the connection but I haven't included it in the code below.
I need a really simple solution because data is only needed locally for the player's progress to be stored so there doesn't need to be a server hosting it if possible.
public string location = #"server=localhost;user=root;database=wattsup;port=3306;Allow User Variables=True"; //Path to database
MySqlConnection con = new MySqlConnection(location);
con.Open();
MySqlCommandBuilder cmdBuilder = new MySqlCommandBuilder();
string tbname = cmdBuilder.QuoteIdentifier(name1);
string query = "SELECT Question FROM " + tbname + " WHERE ID = #value";
MySqlCommand command = new MySqlCommand(query, con);
command.Parameters.AddWithValue("#value", Equations[EquationValue].EquationID);
MySqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
SpaceGame.question = Convert.ToString(reader[0]);
string fileName = #"Question.txt";
//text file created to show me whether it is opened or not
using (StreamWriter fileStream = File.CreateText(fileName))
{
fileStream.WriteLine(SpaceGame.question);
}
}
con.Close();
If you want to store the data in single file, maybe you can try SQLite. The following is the steps that using SQLite you can refer to.
1.Install System.Data.SQLite using NuGet Package Manager.
2.Configure the connection string in App.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
...
<connectionStrings>
<add name="SQLiteDbContext" connectionString="Data Source=MyDatabase.sqlite" providerName="System.Data.SQLite.EF6" />
</connectionStrings>
</configuration>
3.The simple demo that create .sqlite.
// create
SQLiteConnection.CreateFile("MyDatabase.sqlite");
SQLiteConnection m_dbConnection = new SQLiteConnection("Data Source=MyDatabase.sqlite");
m_dbConnection.Open();
string sql = "create table highscores (name varchar(20), score int)";
SQLiteCommand command = new SQLiteCommand(sql, m_dbConnection);
command.ExecuteNonQuery();
sql = "insert into highscores (name, score) values ('Me', 9001)";
command = new SQLiteCommand(sql, m_dbConnection);
command.ExecuteNonQuery();// read
SQLiteCommand sqlCom = new SQLiteCommand("Select * From highscores", m_dbConnection);
SQLiteDataReader sqlDataReader = sqlCom.ExecuteReader();
int i = 1;
while (sqlDataReader.Read())
{
listBox1.Items.Add(i);
listBox1.Items.Add(sqlDataReader.GetValue(0));
listBox1.Items.Add(sqlDataReader.GetValue(1));
i++;
}
m_dbConnection.Close();
Hi I am using SQLite as database in my Unity project. For some reason database file got corrupted but luckily I had backup so I didn't lose anything. I think the reason behind corruption was using unity collab to share database file. My question is what can I do not to corrupt the file again? Also can it corrupt after releasing the game in player's local gamefiles?
And here is the static methods i am using to execute commands, maybe something is wrong with it.
public static void Execute(string command, ref DataTable datatable)
{
string dbPath = ("Data Source=" + Application.dataPath + "/database.s3db");
using (SqliteConnection cnt = new SqliteConnection(dbPath))
{
using (SqliteCommand cmd = new SqliteCommand(command, cnt))
{
using (SqliteDataAdapter adapter = new SqliteDataAdapter(cmd))
{
adapter.Fill(datatable);
}
}
}
}
public static void Execute(string command)
{
string dbPath = ("Data Source=" + Application.dataPath + "/database.s3db");
using (SqliteConnection cnt = new SqliteConnection(dbPath))
{
using (SqliteCommand cmd = new SqliteCommand(command, cnt))
{
cnt.Open();
cmd.ExecuteNonQuery();
cnt.Close();
}
}
}
SQLite implements atomic transactions, but those guarantees hold only as long as the database file is accessed only through the SQLite library.
In your case, it's likely that the database file was copied from your friend's computer in the middle of a transaction, i.e., some changes did not end up in the published version. The only way to avoid this is to ensure that no files are currently being modified when doing the publishing.
I am building a inventory based application that can be directly run from any pc without any installation and so i am using SQL CE.. On Start, I am checking if database is present. If Not i am creating new database as :
try
{
string conString = "Data Source='ITM.sdf';LCID=1033;Password=ABCDEF; Encrypt = TRUE;";
SqlCeEngine engine = new SqlCeEngine(conString);
engine.CreateDatabase();
return true;
}
catch (Exception e)
{
//MessageBox.Show("Database Already Present");
}
The database is created properly and i can access the database to create tables as well.. The Problem i am facing is - I am inserting and updating records in windows form on button click with code :
using (SqlCeConnection connection = new SqlCeConnection(DatabaseConnection.connectionstring))
{
connection.Open();
String Name = NameTxt.Text.ToString();
String Phone = PhoneTxt.Text.ToString();
double balance = Double.Parse(BalanceTxt.Text.ToString());
String City = CityTxt.Text.ToString();
string sqlquery = "INSERT INTO Customers (Name,Phone,Balance,City)" + "Values(#name,#phone, #bal, #city)";
SqlCeCommand cmd = new SqlCeCommand(sqlquery, connection);
cmd.Parameters.AddWithValue("#name", Name);
cmd.Parameters.AddWithValue("#phone", Phone);
cmd.Parameters.AddWithValue("#bal", balance);
cmd.Parameters.AddWithValue("#city", City);
int x = cmd.ExecuteNonQuery();
if (x > 0)
{
MessageBox.Show("Data Inserted");
}
else
{
MessageBox.Show("Error Occured. Cannot Insert the data");
}
connection.Close();
}
and Updation Code is
using (SqlCeConnection connection = new SqlCeConnection(DatabaseConnection.connectionstring))
{
connection.Open();
int idtoedit = select_id_edit;
String Name = NameEditTxt.Text.ToString();
String Phone = metroTextBox1.Text.ToString();
String City = CityEditTxt.Text.ToString();
string sqlquery = "Update Customers Set Name = #name, Phone = #phone,City = #city where Id = #id";
SqlCeCommand cmd = new SqlCeCommand(sqlquery, connection);
cmd.Parameters.AddWithValue("#name", Name);
cmd.Parameters.AddWithValue("#phone", Phone);
cmd.Parameters.AddWithValue("#id", idtoedit);
cmd.Parameters.AddWithValue("#city", City);
int x = cmd.ExecuteNonQuery();
if (x > 0)
{
MessageBox.Show("Data Updated");
}
else
{
MessageBox.Show("Error Occured. Cannot Insert the data");
}
loadIntoGrid();
connection.Close();
}
Whenever i execute code for inserting and updating records - Records are reflected in datagrid filled with adapter from database table. But once i restart the application, values do not appear in database. Once in a million, values are reflected in database. I cannot understand the reason behind this issue.
I have reffered to these articles :
C# - ExecuteNonQuery() isn't working with SQL Server CE
Insert, Update, Delete are not applied on SQL Server CE database file for Windows Mobile
But since i am creating database programmatically - It is getting created directly to bin/debug directory and i cannot see it in solution explorer in visual studio for changing copy options
You probably rewrite your database file with a blank copy from your project.
See this answer. You should not store your database in a bin folder, rather you should find a place in user's or public profile in AppData or another folder, depending on your needs.
The connection string would look like this:
<connectionStrings>
<add name="ITMContext" connectionString="data source=|DataDirectory|\ITM.sdf';LCID=1033;Password=ABCDEF; Encrypt = TRUE;" providerName="System.Data.SqlServerCe.4.0">
You shuld deploy your db file with your custom code run at app's starup to a chosen location, see this ErikEJ blog: http://erikej.blogspot.cz/2013/11/entity-framework-6-sql-server-compact-4_25.html
private const string dbFileName = "Chinook.sdf";
private static void CreateIfNotExists(string fileName)
{
string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
// Set the data directory to the users %AppData% folder
// So the database file will be placed in: C:\\Users\\<Username>\\AppData\\Roaming\\
AppDomain.CurrentDomain.SetData("DataDirectory", path);
// Enure that the database file is present
if (!System.IO.File.Exists(System.IO.Path.Combine(path, fileName)))
{
//Get path to our .exe, which also has a copy of the database file
var exePath = System.IO.Path.GetDirectoryName(
new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath);
//Copy the file from the .exe location to the %AppData% folder
System.IO.File.Copy(
System.IO.Path.Combine(exePath, fileName),
System.IO.Path.Combine(path, fileName));
}
}
Check also this post.
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
The database file in your project can be different when debugging or not. Check also this answer. You might be writting your records to another copy of the database file.