SQLIte from .net framework - c#

My question is how to get SQLite working under .NET framework, v 4.7+, period and where the location of the DB changes with each customer site I install at?
Issue:
My problem with SQLite in .NET framework is I keep getting DLL for SQLite not found or DB factory missing. After spending 3-4 days perusing the i-net and trying different things suggested I've not found a resolve. Maybe I'm that 5-pound hammer is a glass factory 8).
Here's the background:
Requirement is Caller/Host is VBA application, the called "dll" must adhere to COM interface functionality.
I've built a .NET COM exposed DLL that accesses data from a DB using .NET framework 4.7.2, EF 6.4.4 and DBMS SQL Express 2019 which works fine. Challenge is customer IT depts acceptance of solution.
There are 2 DBs, one DB is a read many, write none with 7 tables, one table has 950,000+ rows. The other DB has 2 tables both read many, write occasionally. Both DBs are shared by multiple workstations.
The goal is to replace SQL Express with SQLite. Reason: SQLite is self-contained with no IT involvement to install, except to grant install rights in the first place 8).
Tried XML/Json source file with memory dataset, performance was slow on load, 10-30 seconds, and ran into "out of memory" errors testing with minimal PC spec I find customers using.
Found I can do the data access using .NET 5 or 6 with EF core. I can pass the location of the DB file(s) as required (the DB will be in a folder local or even on a server file share different than my DLL). This took less than a day to get working. The rub here is that .NET framework cannot call .NET DLLs in my testing.
In .NET 6 I call the Class Library as follows:
PostalDataLib tstDB = new(sysDBFQN, custDBFQN);
The Constructor looks like this:
public PostalDataLib(string sysDbFQN, string cusDbFQN)
{
if (!File.Exists(sysDbFQN)) throw new ArgumentException("Invalid FQN, file not found", nameof(sysDbFQN));
if (!File.Exists(cusDbFQN)) throw new ArgumentException("Invalid FQN, file not found", nameof(cusDbFQN));
_custFQN = cusDbFQN;
_sysFQN = sysDbFQN;
_optsPostalData = new DbContextOptionsBuilder<PostalDB>().UseSqlite($"Data Source={sysDbFQN}").Options;
_optsCustData = new DbContextOptionsBuilder<PostalCustDB>().UseSqlite($"Data Source={cusDbFQN}").Options;
}
I then open the DB(s) as follows:
using PostalDB dbctx = new(_optsPostalData);
using PostalCustDB dbctxcus = new(_optsCustData);
But I can't seem to make this workable under .NET framework 4.7.2.

As an update to this.
I've moved the Data access layer into two parts. A tcp Server and the main VBA facing DLL as a TCP client using synchronous methods. This allows for 1 Data access point (added benefit) from multiple PCs. The server side is written using .Net 6.0. The client is written using .Net framework 4.7.2. Using Json payloads as messaging. The TCP elements are using WatsonTCP. Had to use sources not NUget package in the Client to address newtonsoft.Json version issues. By launching the server as a windows scheduler task I get the silent running like a windows service but as I found out without the issue of not finding the appsettings.json file.
The bottom line is it seems that there is no clear information being offered on how to make SQLIte dynamically point to DB via a config file FQN in .net framework 4.7. (not the same as does not support)

Related

Accessing DataVerse data and running SQL statements against it from C# code on .NET 6 (Azure Function)

I'm working with Dynamics365 CE in the cloud. I'm trying to run some rather involved queries that I've built up as SQL scripts (using the wonderful "SQL-4-CDS" plugin for the XrmToolBox).
Now I know I can connect to the Dataverse data store through the TDS endpoint (if enabled - it is in my case), and from SSMS, it works just fine:
Server Name = myorg.crm4.dynamics.com,5558
Authentication = Azure Active Directory - Password
User Name = my company e-mail
I can connect to Dataverse, and run my queries - all is great.
Now I'd like to do the same from C# code (running on .NET 6) that I'm writing, that should end up being an Azure Function in the end - so it's a "server-to-server", behind-the-scenes, no interactive login context kind of scenario.
I can connect to Dataverse via the TDS endpoint using this connection string - as long as I'm running the app interactively - as me, in my user context:
Server=myorg.crm4.dynamics.com,5558;Authentication=Active Directory Password;Database=my_dbname;User Id=my_email;Password=my_pwd;
However - this won't work with a server-to-server "daemon"-style setup.
Since I'm using .NET 6 (for the Azure Function), and since I want to run some custom SQL statements, I cannot use the "CRM XRM Client" tooling (with the IOrganizationService classes) - I need to use straight ADO.NET - any idea would I could define an ADO.NET compatible connection string, that would use a Client ID and Client Secret (which I both have at my disposal)?
I've tried a great many values for the Authentication=...... setting - but none have worked so far. Any place I can find a complete list of the supported values for this connection string parameter?
Thanks for any help or pointers!

C# Executing a query and getting data out of an Access Database (accdb) without using ACE.OLEDB

I'm writing a WPF application.
Trying to use the normal method of getting a connection returns an error similar to: "The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine."
ACE.OLEDB has never been installed on this machine so this error makes sense.
I'm trying to create this application in a way so that our users won't need to contact IT to have the application installed. Getting IT involved is a no go situation and the project will be abandoned.
Another team has an Access database (accdb) that I want my application to extract information (only read, no insert or update). I talked to the team and they won't convert this database back to an earlier version (mdb).
After my research I assume that installing ACE.OLEDB without using Admin privileges is impossible. Because of this and my application requirement of not requiring admin privileges I need to start looking for "Mutant"/Dirty solutions that don't involve ACE.OLEDB.
I tried using power-shell but I'm getting the same problems as I had with C# (requires IT to install ACE.OLEDB).
I have two potential solutions. One write a VBA script that opens up the database and dumps a query result into a file. My C# application would call this VB script and then parse the created file.
The second option is to create a new Access process using Process.Start(fullFilePath) and somehow pass the command to execute a query and somehow pass the results back to the executing application (either via a method return or first to a file).
How would you get the data out?
Is there a way for C# to duplicate the DB file and convert it from (accdb -> mdb)?
This is the second question I ask that is very similar.
C# Connecting to Access DB with no install
The difference between the two (to prevent this is a duplicate question) is that in the previous question I was looking for ways to install ACE.OLEDB without admin privileges while here I'm just looking for any other work around.
Found a workaround. It uses Microsoft.Office.Interop.Access found in NuGet.
var accApp = new Microsoft.Office.Interop.Access.Application();
accApp.OpenCurrentDatabase(#tests.DatabasePath);
Microsoft.Office.Interop.Access.Dao.Database cdb = accApp.CurrentDb();
Microsoft.Office.Interop.Access.Dao.Recordset rst =
cdb.OpenRecordset(
"SELECT * FROM Users",
Microsoft.Office.Interop.Access.Dao.RecordsetTypeEnum.dbOpenSnapshot);
while (!rst.EOF)
{
Console.WriteLine(rst.Fields["username"].Value);
rst.MoveNext();
}
rst.Close();
accApp.CloseCurrentDatabase();
accApp.Quit();

Using ServiceStack Redis from .net core and connecting to Sentinel setup

I have created a .net core console application and included the ServiceStack.Redis.Core v1.0.23 nuget package. I also have the redis sentinel setup running locally. When I try to connect to redis using the sentinel connection method the application hangs on sentinel.start(). There are no errors returned.
If I create the same application using a windows console application using a standard windows C# project and including the ServiceStack.Redis v4.5.4 nuget package the same connection code works fine.
I have also managed to connect from an .net core application using a single redis instance, but not using the sentinel.
Has anyone else experienced this or know of a way to get this working inside a .net core application?
Code used to try to connect:
var sentinelHosts = new[] { "127.0.0.1:26380", "127.0.0.1:26381", "127.0.0.1:26382" };
var sentinel = new RedisSentinel(sentinelHosts, masterName: "mymaster");
var clientManager = sentinel.Start();
It's a bug, which should be fixed with this commit. sentinel.Start() makes a call to RedisPubSubServer which blocks current thread on .NET Core and that is why control does not return back and hangs. This change will be available on nuget with ServiceStack.Redis.Core v1.0.25 package.

C# Project - InstallShield , MySql error when run after installation

I have a project in C# which is created in Visual Studio 2013. I want to create an installer using Install Shield free version. I created an installer and trying to run it on other computer but, when I run it and trying to log into program, I have problems about mysql database. Error message is:
Unhandled exception has occured in you application. If you click Continue, the application will ignore this error and attempt to continue. If you click Quit, the application will close immediately.
Cannot connect.
If I click on details button, I have a serie of errors which refers on Mysql. Example:
System.Exception: Cannot connect ---> MySql.Data.MySqlClient.MySqlException: Unable to connect to any of the specified MySQL hosts.
at MySql.Data.MySqlClient.NativeDriver.Open()
at MySql.Data.MySqlClient.Driver.Open()
at MySql.Data.MySqlClient.Driver.Create(MySqlConnectionStringBuilder settings)
at MySql.Data.MySqlClient.MySqlPool.GetPooledConnection()
at MySql.Data.MySqlClient.MySqlPool.TryToGetDriver()
at MySql.Data.MySqlClient.MySqlPool.GetConnection()
at MySql.Data.MySqlClient.MySqlConnection.Open()
at simulator.ConnConfig.getConnection()
simulator is the name of the project. ConnConfig is a class where is the connection and getConnection() is a function from ConnConfig which return connection. II tried to install on another computer .NET Framework 4.5.2, SQL Server, but also didn't worked.
In my project, I use localhost server where I have a database with 2 tables. My question is, is there any possibility to add that localhost database to installer and use it on another computer? And what redistributables requires this operation? Also, I have installed on computer .NET Framework 4.5, Sql Server 2012..but when I try do add them in InstallShield via Redistributables, but it keeps saying that Needs to be downloaded. Why?
UPDATE
I have this Class where I make the conenction. But I receive error: Additional information: Illegal characters in path. at that line:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SQLite;
namespace simulator
{
class ConnConfig
{
private static string conn = "Data Source=c:\aplicatie.db;Version=3;Password=myPassword;";
public static SQLiteConnection connect = null;
private ConnConfig()
{
}
public static SQLiteConnection getConnection()
{
SQLiteConnection connect = null;
try
{
connect = new SQLiteConnection(conn);
connect.Open();// here I receive the error
return connect;
}
catch (SQLiteException e)
{
throw new Exception("Cannot connect", e);
}
}
}
}
UPDATE 3
In that class I make the connection to database. In the other forms I just use tables and their data. For connection to program, I use a login form which uses this class to getConnection(). I created that database by adding an ADO.NET in simulator project. And with that, it comes those 2 tables that I already have in localhost server. So, Is ok if I have to create another empty database with new tables, but where to include that code or how to use it, because I don't get how that script works..where should I put it?
If your database is going to be installed on each client and your tables are not massive you might want to look at something lighter like SQLite which doesn't need any installation just the dlls and is very fast and efficient and only runs when your program does.
As for for the Needs to be Downloaded issue, it seems you have not setup your prerequisite correctly, you an correct this by following the steps in this article
Adding InstallShield Prerequisites, Merge Modules, and Objects to Basic MSI and InstallScript MSI Projects
You might want to look into determining if MySQL is the right solution for you.
SQLite vs MySQL vs PostgreSQL: A Comparison Of Relational Database Management Systems
And to see the limitations of SQLite SQLite
Because honestly seems like overkill to install MySQL on every system. If you had one server with MySQL on the network, okay. But on every system seems like a bad idea.
As far as connecting to an SQLite database here is a List of Connection Strings for SQLite
See this topic on how to create Databases and tables Create SQLite Database and table
My guess is your program doesn't bundle up the database alongside the setup upon deployment. This may be due to the fact that you didn't mark your database as a Data File in the Project Files. Try this, right click on your project name in Solution Explorer and select Properties from Menu. From the horizontal tabs click on the Publish Tab. Under Install Mode and Settings click the Application Files button. A dialog box appears with all Application files. Set your database Publish Status to Data File from the drop down on the corresponding cell. This way your database will be bundled together with the setup upon publishing. Hope this helps.
You can access SQLite via ODBC.

Mono Develop Microsoft Authentication for Microsoft Analysis server

For my research I need to be able to query a Microsoft analysis server(2012) Data cube with the Unity game engine. For the connection there is a Microsoft Authentication needed and Unity is using the Mono Develop libraries for SQL connections which gives me a problem. Since so far i haven't found a solution for Mono to be able to use a Microsoft Authentication.
I want to find a nice way to use windows authentication inside a domain at the customer. Since the end application must be able to connect to Data cubes preferably using a connection string.
Data cubes using an IIS server that allows for HTTP connection using SOAP will not always be available depending on the costumer set-up.
Also the desire to build the application on multiple platforms makes it hard to add custom library's if there even is a custom library for this request since I haven't been able to find one yet.
My current less fortunate side options are:
Build an extra windows application with visual studio that query's the data and parses it to Unity (But requires and extra application to
run).
Use the http SOAP connection with an IIS service (But requires the analysis server to be set-up with IIS which isn't always possible depending on the customer).
Find a library that allows me to use Microsoft Authentication (but probably only works on the windows platform, or doesn't work with Unity).
I'm hoping someone has already found or maybe knows a good solution that works for Unity without giving the limitations I've mentioned above.
I am using the Microsoft.AnalysisServices.AdomdClient; with visual studio that works fine for visual studio build but doesn't work in monodevelop in unity.
try
{
using (AdomdConnection adcon = new AdomdConnection(connectionString))
{
adcon.Open();
using (AdomdCommand adcmd = adcon.CreateCommand())
{
adcmd.CommandText = textBox3.Text.ToString();
AdomdDataReader dr = adcmd.ExecuteReader(CommandBehavior.CloseConnection);
while (dr.Read())
{
for (int i = 0; i < dr.FieldCount; i++)
textBox2.AppendText(dr[i] + (i == dr.FieldCount - 1 ? "" : ", ") + Environment.NewLine);
}
dr.Close();
textBox2.AppendText(adcmd.CommandText.ToString() + Environment.NewLine + Environment.NewLine);
adcmd.Connection.Close();
}
adcon.Close();
}
}
catch(Exception e)
{
textBox2.AppendText(e.ToString() + Environment.NewLine);
}
Thank you for any suggestions, feedback or answers!
Something you could try would be using the relational SQL Server engine as a kind of proxy. The relational SQL Server engine should be available whereever Analysis Services is available.
You could set up a linked server in the relational SQL Server which links to the Analysis Services server using the Analysis Services OLEDB client. How to set up linked servers is described here.
Then you can send MDX to this linked server, and get back the results in the relational engine like this:
select * from openquery(AdventureWorksOLAP,
'select [Measures].[Sales Amount] on columns from [Adventure Works]')
where AdventureWorksOLAP is the name of your linked server.
However, you should be aware that the column names are strange (containing closing square brackets, which need to be escaped within the square brackets enclosing column names by doubling). E. g. the above query would have a column that you have to access as [[Measures]].[Sales Amount]]]. Furthermore, all cell values come back as nvarchar and might need to be casted to a numeric type in order to work with them.
Maybe you could encapsulate the column name changing and column typecasting into a stored procedure.
And you could use SQL server authentication to access the relational database.

Categories