Unity SQLite local database - c#

I am making a small game in Unity and I'm in need of a database. I tried using SQLite database because that seemed to be recommended by the web.
Now I'm having troubles with actually connecting to the local database via c#.
I implemented the Data in SQLite .dll's.
I am trying to get 1 name from the database that I created using SQLite developer.
Below is my DataConnection class, which I use to connect to the database.
using UnityEngine;
using System.Collections;
using System.Data;
using Mono.Data.SqliteClient;
public class Dataconnection : MonoBehaviour {
private string _constr = #"Data Source=C:\Program Files (x86)\SharpPlus\SqliteDev\GameDatabase.db;Version=3;";
private IDbConnection _dbc;
private IDbCommand _dbcm;
private IDataReader _dbr;
public Dataconnection()
{
}
public Dataconnection(string constring)
{
_constr = constring;
}
public string ExcecuteQuery(string SQL)
{
string output = "";
try
{
_dbc = new SqliteConnection(_constr);
_dbc.Open();
_dbcm = _dbc.CreateCommand();
_dbcm.CommandText = SQL;
_dbr = _dbcm.ExecuteReader();
}
catch
{
}
while (_dbr.Read())
{
output = _dbr.GetString(0);
}
_dbc.Close();
return output;
}
}
Then I call the following method from another class:
datacon.ExcecuteQuery("SELECT name FROM employee WHERE empid = 1;");
I get the following errors when running the code:
So I'm guessing it has something to do with a 32/64 -bit mismatch or is there something wrong with creating an instance of a script like this?:
private Dataconnection datacon;
void Start()
{
datacon = new Dataconnection();
}
Happy to receive any help at all. I'm familiar with using database, just new to SQLite.

It says it cannot load the native sqlite.dll because you have there 64 bit version and it needs 32 bit
Place this in your app folder https://www.sqlite.org/2015/sqlite-dll-win32-x86-3081001.zip
Please fill that empty catch on line 38 with a throw;
as there is an exception hidden there which is the true cause of the null reference.
You could also post your connection string so I could make this answer better.

I got it working now. The problem was my that one of the SQLite .dll's was still 32bit. I did this tutorial over again and searched google for the 64bit .dll files and now it's working.

Related

Alternate Database Connection in C#

Please someone help me - I have a problem.
I'm trying to code an alternate database for a program I am writing in C#. You see on the website I managed to do it with an if..
This is my php code:
//database connection
$conexion = #mysqli_connect("localhost","todo","todo","dbdaq");
//if mainserver connection is not made then it connects to secondary server
if (!$conexion){
$conexion = mysqli_connect("192.168.0.12","todo","","dbdaq");
}
And that works in PHP, but when I try to write something like that in C#, I can't manage to do it.
Here is my database connection class in C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MySql.Data;
using MySql.Data.MySqlClient;
namespace ComunicacionCSharp
{
class ConexionBD
{
public static MySqlConnection ObtenerConexion()
{
MySqlConnection Conectar = new MySqlConnection("Server =localhost; database = dbdaq ; Userid = root; password =");
return Conectar;
}
}
}
NOTE: this class is called from my main GUI interface.
namespace ComunicacionCSharp
{
public partial class Login : Form
{
MySqlConnection conn = ConexionBD.ObtenerConexion();
public string usuario;
public Login()
{
InitializeComponent();
}
}
}
Can someone please help me? I use to have another version of the database connection with an error message if the connection is not found, but I left coding in C# for a while and could not find that piece of code anymore, and I don't remember how to do it :(
mysqli_connect returns a handle to an open connection and in your C# code you pass an unopened connection. You must change a bit your code, something like this:
public static MySqlConnection ObtenerConexion()
{
MySqlConnection Conectar = null;
try
{
Conectar = new MySqlConnection(yourFirstConnectionString);
Conectar.Open();
}
catch
{
try
{
Conectar = new MySqlConnection(yourSecondConnectionString);
Conectar.Open();
}
catch{ }
}
return Conectar;
}
Remember to check the connection wherever you use it, if both connections fail it will return null.

Autocad & System.Addin, FileNotFoundException for Autocads basic dlls

i just started to develop applications for AutoCAD 2016. I want to load my dLLs into a separate AppDomain, so that i don't have to restart ACAD all the time.
After a lot of research and trying i ended up with a pipeline solution
using System.Addin and System.Addin.Contract.
I use only interfaces and standardclasses for the Views Contract and Adapters like in this example here.
This is my addin containing one methode to write Hello into Acad's Editor and a second methode for drawing a line.
using System.AddIn;
using CADAddinView;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
namespace CADAddIn
{
[AddIn("cadAddIn", Version = "1.0.0.0")]
public class CADAddIn : ICADAddinView
{
public void drawLine()
{
Document acDoc = Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;
using (DocumentLock acLckDoc = acDoc.LockDocument())
{
using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
DBObject blkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead);
BlockTable acBlkTbl = blkTbl as BlockTable;
BlockTableRecord acBlkTblRec = (BlockTableRecord)acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
Polyline acPoly = new Polyline();
acPoly.SetDatabaseDefaults();
acPoly.AddVertexAt(0, new Point2d(0, 0), 0, 0, 0);
acPoly.AddVertexAt(0, new Point2d(100, 100), 0, 0, 0);
acBlkTblRec.AppendEntity(acPoly);
acTrans.AddNewlyCreatedDBObject(acPoly, true);
acTrans.Commit();
}
}
}
public void sayHello()
{
Editor ed = Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument.Editor;
ed.WriteMessage("Hello");
}
}
}
this is my HostApplication:
using System.AddIn.Hosting;
using System.Windows.Forms;
using CADHostView;
using System;
using System.Collections.ObjectModel;
using Autodesk.AutoCAD.Runtime;
namespace CADHost
{
public class CADHost
{
[CommandMethod("sayHello")]
public static void sayHello()
{
string addInPath = Environment.CurrentDirectory + "\\Pipeline";
string[] warnings = AddInStore.Update(addInPath);
foreach (string warning in warnings)
{
MessageBox.Show(warning);
}
Collection<AddInToken> tokens = AddInStore.FindAddIns(typeof(ICADHostView), addInPath);
if (tokens.Count == 0)
{
MessageBox.Show("No AddIn found.");
}
else
{
AddInToken cadToken = tokens[0];
ICADHostView cadApp = cadToken.Activate<ICADHostView>(AddInSecurityLevel.Host);
cadApp.sayHello();
}
}
[CommandMethod("drawLine")]
public static void drawLine()
{
string addInPath = Environment.CurrentDirectory + "\\Pipeline";
string[] warnings = AddInStore.Update(addInPath);
foreach (string warning in warnings)
{
MessageBox.Show(warning);
}
Collection<AddInToken> tokens = AddInStore.FindAddIns(typeof(ICADHostView), addInPath);
if (tokens.Count == 0)
{
MessageBox.Show("No AddIn found.");
}
else
{
AddInToken cadToken = tokens[0];
ICADHostView cadApp = cadToken.Activate<ICADHostView>(AddInSecurityLevel.Host);
cadApp.drawLine();
}
}
}
}
Both of the two applications reference to three standard-Dlls from Acad:
accoremgd.dll, acdbmgd.dll, acmgd.dll.
In both projects these dlls have the option local copy false.
If i start then i get an Exception, where the programm cannot find the file "accoremgd.dll" and Acad crashes.
So i tried to set the Option local copy true only for the Addin.
Now it works for the "sayHello"-Methode.
but i get an invalide cast exception when acBlkTbl is initialised.
Would be great if someone has the last steps for me to make this work.
Also great would be a working example must not be made with the Addinsystem
i only want to make this work for not restarting acad all the time^^
Thank you for your help
matthias
I don't believe a separate AppDomain will work, when you call AutoCAD object types it will go to the main AppDomain and get messed up...
As just want to edit your code and don't restart, you'll be better with Edit & Continue feature (available since VC2013 on AutoCAD 2015, I believe).
This is not supported. AutoCAD is a very old and complex program and most of the AutoCAD API objects cannot be used in remote fashion.
Please read:
http://through-the-interface.typepad.com/through_the_interface/2008/09/tired-of-not-be.html
http://forums.autodesk.com/t5/net/netload-is-there-a-net-unload-command/td-p/2404002
https://www.theswamp.org/index.php?topic=38675.0
In the #3, you can see that the AutoCAD development team confirmed that there are some global variables which will prevent working this way.
I gave up my tries to solve this problem. My current "best" solution is to load dlls at the start of AutoCAD. At least i don't have to netload every dll.
If someone has a better solution feel free to tell me^^ Thanks to all that answered. matthias

Why can't I read a db4o file created by a Java app in a C# app?

I have a db4o database that was generate by a Java app and I'm trying to read it using a C# app.
However, when running the following line of code:
IObjectContainer db = Db4oEmbedded.OpenFile(#"..\..\..\Databases\people.db4o");
I get the following error:
Unable to cast object of type
'Db4objects.Db4o.Reflect.Generic.GenericObject' to type
'Db4objects.Db4o.Ext.Db4oDatabase'.
Any ideas? I know there are person objects that contain personId fields (along with others) in the DB. I'm using db4o version 8. I'm not sure what version was used to generate the database.
The entire program is:
using System;
using System.Collections.Generic;
using System.Linq;
using Db4objects.Db4o;
using Db4objects.Db4o.Config;
using MyCompany.Domain;
namespace MyCompany.Anonymizer
{
internal class Program
{
// Private methods.
private static IEmbeddedConfiguration ConfigureAlias()
{
IEmbeddedConfiguration configuration = Db4oEmbedded.NewConfiguration();
configuration.Common.AddAlias(new TypeAlias("com.theircompany.Person", "MyCompany.Domain.Person, MyCompany.Domain"));
configuration.Common.Add(new JavaSupport());
return configuration;
}
private static void Main(string[] args)
{
IObjectContainer db = Db4oEmbedded.OpenFile(#"..\..\..\Databases\people.db4o");
try
{
IList<Person> result = db.Query<Person>();
for (int i = 0; i < result.Count; i++)
{
Person person = result[i];
Console.WriteLine(string.Format("Person ID: {0}", person.personId));
}
}
finally
{
db.Close();
}
}
}
}
The most common scenario in which this exception is thrown is when db4o fails to resolve the type of a stored object.
In your case, db4o is failing to read one of its internal objects which makes me believe you have not passed the configuration to the OpenFile() method (surely, the code you have posted is not calling ConfigureAlias() method);
Keep in mind that as of version 8.0 no further improvement will be done regarding cross platform support (you can read more details here).

How to release COM handle in .NET

I am using the following code under ASP.NET 4.0 framework to obtain the version of MSI file from a web app:
string strVersion = "";
try
{
Type InstallerType;
WindowsInstaller.Installer installer;
InstallerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
installer = (WindowsInstaller.Installer)Activator.CreateInstance(InstallerType);
WindowsInstaller.Database db = installer.OpenDatabase(strMSIFilePath, 0);
WindowsInstaller.View dv = db.OpenView("SELECT `Value` FROM `Property` WHERE `Property`='ProductVersion'");
WindowsInstaller.Record record = null;
dv.Execute(record);
record = dv.Fetch();
strVersion = record.get_StringData(1).ToString();
dv.Close();
//db.Commit();
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(dv);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(db);
}
catch
{
//Failed
strVersion = "";
}
It works fine except that when the code finishes running it holds an internal MSI file handle so when I try to move or rename the MSI file I get the error that the file is still in use. This continues until I actually navigate away from the ASPX page that calls the method above.
My question is, I obviously didn't close some handle or object in the code above. But what could that be?
PS. I'm testing it in a development IDE from VS2010.
EDIT: Edited the code like it should be after Adriano's suggestion. Thanks!
The COM object has not been released (it should be auto-released when it goes out of scope but in .NET this doesn't work really well). Because it does not implement the IDisposable interface you can't call its Dispose() method and you can't use it inside an using statement. You have to explicitly call Marshal.FinalReleaseComObject. For example:
try
{
// Your stuffs
}
finally
{
dv.Close();
Marshal.FinalReleaseComObject(dv);
Marshal.FinalReleaseComObject(db);
}
Moreover note that you do not really need a call to the Commit() method because you didn't make any change but just a query.
FWIW, you should be using Windows Installer XML (WiX) Deployment Tools Foundation (DTF). It's an FOSS project from Microsoft that can be found on CodePlex. It has MSI interop libraries with classes that are very similar to the COM classes but implement IDisosable and use P/Invoke instead of COM behind the scenes. There is even support for Linq to MSI if you want. And the full source code is available.
DTF is the gold standard for MSI interop in a .NET world. Here are two examples:
using System;
using System.Linq;
using Microsoft.Deployment.WindowsInstaller;
using Microsoft.Deployment.WindowsInstaller.Linq;
namespace ConsoleApplication3
{
class Program
{
const string DATABASE_PATH = #"C:\FOO..MSI";
const string SQL_SELECT_PRODUCTVERSION = "SELECT `Value` FROM `Property` WHERE `Property`='ProductVersion'";
static void Main(string[] args)
{
using (Database database = new Database(DATABASE_PATH, DatabaseOpenMode.ReadOnly))
{
Console.WriteLine(database.ExecuteScalar(SQL_SELECT_PRODUCTVERSION).ToString());
}
using (QDatabase database = new QDatabase(DATABASE_PATH, DatabaseOpenMode.ReadOnly))
{
var results = from property in database.Properties where property.Property == "ProductVersion" select property.Value;
Console.WriteLine(results.AsEnumerable<string>().First());
}
}
}
}
try to Dispose the Objects.
dv.Dispose();
db.Dispose();

How to access database in lightswitch in other class?

I just don't know how to explain this clearly. So I create a simple image pattern of what I did.
My question is, how would I be able to access my database in other class in LS?
I've been searching on net, but I didn't found any solution. I hope I'll find it here.
Thanks!.
Any suggestion is already appreciated.
Thanks for the answer Bryan, but I found the answer on my problem here Richard Waddell
Here is what I did to achieve my goal.
Switch your LS project to file view
Go to "Common" project, under "UserCode" folder, create a class (e.g. Authenticate.cs) and put this codes.
The code follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.LightSwitch;
namespace LightSwitchApplication
{
public class Authenticate
{
public static adminuser GetCurrentUser()
{
adminuser userFound = (from useritem in
Application.Current.CreateDataWorkspace().basecampcoreData.adminusers
where useritem.LoginID == Application.Current.User.Name
select useritem).SingleOrDefault();
if (userFound != null)
return userFound;
else
return null;
}
}
}
Then you can now call the Authenticate.GetCurrentUser() anywhere in the project.
Thanks!
The main difference is the first set of code that works is running inside a screen. For your Authenticate class, you need to do the following steps to access the Database.
Note: I'm assuming that your datasource has the default name of ApplicationData since you hid the name, if not, make the corresponding changes. If it's a completely different datasource, change "_IntrinsicData" in the steps below)
These steps are taken from the Lightswitch Help Website
Navigate to ..ServerGenerated\GeneratedArtifacts (in the LightSwitch project) and click on ApplicationData.cs and Add As Link.
Add the following code below, this code dynamically creates a connection to the database. LightSwitch uses “_IntrinsicData” as it’s connection string.
private ApplicationDataObjectContext m_context;
public ApplicationDataObjectContext Context
{
get
{
if (this.m_context == null)
{
string connString =
System.Web.Configuration.WebConfigurationManager
.ConnectionStrings["_IntrinsicData"].ConnectionString;
EntityConnectionStringBuilder builder = new EntityConnectionStringBuilder();
builder.Metadata =
"res://*/ApplicationData.csdl|res://*/ApplicationData.ssdl|res://*/ApplicationData.msl";
builder.Provider =
"System.Data.SqlClient";
builder.ProviderConnectionString = connString;
this.m_context = new ApplicationDataObjectContext(builder.ConnectionString);
}
return this.m_context;
}
}
You should be able to access it through Context.adminusers

Categories

Resources