Referring external DLLs in WPF crashing Application - c#

I have used following 3 SQL Server (Version SQL Server 2008 R2) DLLs in a WPF project:
Microsoft.SqlServer.ConnectionInfo
Microsoft.SqlServer.Management.Sdk.Sfc
Microsoft.SqlServer.Smo
Project works fine on the machine on which it was developed. However if I try to move the .exe to some other machine then application gets crashed.
I have set Copy Local = True for all the 3 DLLs so that during compilation it should copy all the 3 DLLs inside Debug folder. (These DLLs are required to find out the SQL Server DATA Root Directory.)
Following the code which I am trying to execute in my App.
try
{
MessageBox.Show("trying to open connection");
string conStr = System.Configuration.ConfigurationManager.ConnectionStrings["MyConnectionString"].ToString();
con = new SqlConnection(conStr);
con.Open();
MessageBox.Show("connection opened ");
var serverConnection = new ServerConnection(con);
var server = new Server(serverConnection);
var defaultDataPath = string.IsNullOrEmpty(server.Settings.DefaultFile) ? server.MasterDBPath : server.Settings.DefaultFile;
var defaultLogPath = string.IsNullOrEmpty(server.Settings.DefaultLog) ? server.MasterDBLogPath : server.Settings.DefaultLog;
string restoreSql = #"RESTORE DATABASE [MyDB]
FROM DISK = '" + this.FilePath + #"'
WITH
MOVE 'MyDB' TO '" + defaultDataPath + #"\MyDB.mdf',
MOVE 'MyDB_Log' TO '" + defaultLogPath + #"\MyDB_Log.ldf',
RECOVERY, REPLACE, STATS = 10";
SqlCommand restoreCmd = new SqlCommand(restoreSql, con);
int status = restoreCmd.ExecuteNonQuery();
completedFlag = true;
}
catch (Exception ex)
{
MessageBox.Show("Database Restore Error: " + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
if (con.State == ConnectionState.Open)
{
con.Close();
}
}
if (completedFlag)
MessageBox.Show("Database restore successful.", "Information", MessageBoxButton.OK, MessageBoxImage.Information);
else
MessageBox.Show("SYSTEM ERROR: Failed restoring database.\nPlease restart SQL Server Service and try again.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
Not able to find out why my application is crashing.

When distributing certain packages, just including the dll within your package may not help. You need to read the distribution guidelines of those libraries.
In the case of SMO, this is what MSDN says
If you develop an application that uses SQL Server Management Objects,
you need to make sure that the necessary support files are present on
the computer with the application. The SQL Server 2008 feature pack
contains a redistributable package for the SQL Server Management
Objects.
If you have these support packages installed with your external libraries, your problem should be solved.

Related

Import from excel error Microsoft.ACE.OLEDB.12.0 provider is not registered on the local machine

i try to use ms interopt to import data from excel file, i have install Microsoft office 2007 in my computer and working fine, when i use the code in another computer have Microsoft office 2019 installed i face this error, i install
Microsoft Access Database Engine 2010 Redistributable
but not fix the problem , also i search fro link of 2007 System Driver Data Connectivity Component, but i cannot find any one, and Microsft has remove the file, this is my code:
using System.Data.OleDb;
OleDbConnection conn=null;
DataTable ExcelDataTables = null;
try {
conn = new OleDbConnection();
conn.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + ExcelFilePath + ";Extended Properties=" + "\"Excel 12.0 Xml;HDR=YES;IMEX=1\"";
conn.Open();
ExcelDataTables = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
String[] ExcelSheetNames = new String[ExcelDataTables.Rows.Count];
int i = 0;
// Add the sheet name to the string array.
foreach (DataRow row in ExcelDataTables.Rows)
{
ExcelSheetNames[i] = row["TABLE_NAME"].ToString();//.Replace("'","").Replace("$", "");
i++;
}
// Loop through all of the sheets if you want too...
/*for (int j = 0; j < excelSheets.Length; j++)
{
// Query each excel sheet.
}*/
conn.Close();
conn = null;
LSTBox_ExcelSheetNames.DataSource = ExcelSheetNames;
}
catch (Exception ex)
{
if (conn != null)
conn.Close();
conn = null;
ExcelDataTables = null;
FRM_MSG f = new FRM_MSG();
f.ShowDLG(" ",
ex.Message + "\n" + ex.StackTrace.ToString(),
FRM_MSG.MSGIcon.Error,
FRM_MSG.BTNS.One,
new string[] { "Ok" });
}
please give me a link to 2007 System Driver Data Connectivity Component.
The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine.
The documentation states MS Access drivers (including the OLEDB driver) only work under the x86 platform and is incompatible under the x64 or AnyCPU platform. However this appears to be untrue. Ref: https://stackoverflow.com/a/32760211/495455
First download the Microsoft Access Database Engine 2010 Redistributable making sure you tick the _64.exe version: http://www.microsoft.com/en-us/download/details.aspx?id=13255
Extract the AccessDatabaseEngine_x64.exe to a folder to get the AceRedist.msi and Data.cab files.
Open command prompt in Admin mode
cd to the folder you extracted the download and execute the MSI with the passive argument:
AceRedist.msi /passive
After these steps you should be able to run the application after building in x64 or AnyCPU build configuration.

Unable to Load DLL 'sqlite.interop.dll' After Create Setup File

I am working on a windows application using Visual studio 2015(Professional) and Sqlite DataBase, windows 8.1(x64). i Install Sqlite From Nuget it Autometically install These References... system.componentmodel.dataannotations, System.Data.SQLite, System.Data.SQLite.EF6, System.Data.SQLite.Linq .
when i execute my app in visual Studio, Everything is working Fine. then Publish it by Windows Setup. then Install The Newly Created Setup File on My machine windows 8.1(x64). Whenever i try to Run it and Click on Login Button it gives the following error
"unable to load dll 'sqlite.interop.dll': the specified module could not be found. (exception from hresult: 0x8007007e)".
my Code is...
string connectionString = #"Data Source = SampelTest.db; Version = 3; new = false; compress = true; ";
private void buttonLogin_Click(object sender, EventArgs e)
{
using (SQLiteConnection con = new SQLiteConnection(connectionString))
{
try
{
using (SQLiteCommand sqlcmd = new SQLiteCommand("select count(*) from [SampelTest]", con))
{
con.Open();
Int32 count = Convert.ToInt32(sqlcmd.ExecuteScalar());
con.Close();
if (count > 0)
{
MessageBox.Show("User have in DataBase");
}
else
{
MessageBox.Show("Empty DataBase");
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
}
}
}
My Database file in the Debug Folder "SampelTest.db"i already tried these step that are from Google to resolve my problem.
Coppy Sqlite.Interop.dll File From x64 To Debug Folder.
create x86 and x64 folder from solution Explorar and add Sqlite.Interop.dll from x86 and x64 respectively and Set Property, Build Option => Content, Copy to output Directory => Copy always.
Unchake the Prefer 32-bit.
After Try these steps can't able to solve this problem. Please Help to me to solve this. Thanks For Looking.

SQL CE Not updating database values from windows forms

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.

WPF, What's the best way to store a constant to be used at startup?

I have a WPF application that accesses a database instance. I develop on my personal machine and the application will run on another machine and database instance. Is there a way or best practice for storing the instance name outside of the WPF application that I can read upon app startup? Currently I have comment and uncomment the database instance name as I move from machine to machine. I would like to have something stored on the local machine that I can just read when the application is launched.
Here is what I currently do:
try
{
if (sqlConn != null)
{
sqlConn.Close();
}
strConnection = "Data Source=" + strDBInstance + "; Initial Catalog=NBFoodPantry;Integrated Security=true; MultipleActiveResultSets = True";
//strConnection = "Data Source=CASS-LAPTOP\\SQLEXPRESS; Initial Catalog=NBFoodPantry;Integrated Security=true; MultipleActiveResultSets = True";
//strConnection = "Data Source=KENTS-WORK-PC\\CASS_SQLEXPRESS; Initial Catalog=NBFoodPantry;Integrated Security=true; MultipleActiveResultSets = True";
sqlConn = new SqlConnection(#strConnection);
try
{
sqlConn.Open();
}
catch (Exception ex)
{
string strMsg;
WriteErrorLog(strErrorLogFile, "ConnectToDatabase", ex.Message, false);
strMsg = "ConnectToDatabase: SQL Open failed. Please make sure that you database ";
strMsg += "instance and name are correct. Also make sure that the SQL engine is running.";
System.Windows.MessageBox.Show(strMsg);
}
}
catch (Exception ex)
{
string strMsg;
WriteErrorLog(strErrorLogFile, "ConnectToDatabase", ex.Message, false);
strMsg = " ConnectToDatabase: failed with error, " + ex.Message + ".";
System.Windows.MessageBox.Show(strMsg);
}
This is what application settings are designed to handle. Under the properties node in your project, open the settings. This has built in support for connection strings:
Then you can access the settings in your code by its name:
Properties.Settings.Default.ConnectionString
All of this is stored in your App.config, which you can modify on various machines to have different values.

SQL Server Compact edition 3.5 database acess is denied

I have developed a desktop application in C# with Microsoft SQL Server Compact Edition 3.5.
It works fine when I run .exe file from solution folder (bin\release or debug) but when I tried to deploy it by creating its setup it shows unhandled exception:
You don't have permission to access CustomersDB.sdf file.
Note there is no path error it is correct.
string lokasifile = Environment.CurrentDirectory + "\\CustomersDB.sdf";
string stringkoneksi = "Data Source = \"" + lokasifile + "\"";
SqlCeConnection koneksi = new SqlCeConnection(stringkoneksi);
koneksi.Open();
SecurityException
This is nothing but caller does not have the appropriate permission.
Environment.CurrentDirectory Property
try
{
//Call Path here you will get to what the exactly error is
}
catch (Exception ex)
{
if (ex is DirectoryNotFoundException|| ex is IOException|| ex is SecurityException)
{
//Your handling here
}
else
{
throw;
}
}

Categories