Dynamically creating a connection string for a database just created - c#

I have created a database programmatically.
Is there any way to create its connection string dynamically using C#, so that after the database creation all data is stored in the new database using C#.

You could also used nuget which will create ConnectionString for you.
After installing package
Install-Package ConnectionStringPT
You will just need to invoke:
var connectionString = ConnectionString.GetSqlServerConnectionString("localhost", "dbName");

I have use this in my C# widows form app and it works for me. Change it according to your needs.
You need to add namespace:
//using Microsoft.SqlServer.Management.Smo;
using System.Data.SqlClient;
and add below code:
try
{
SqlConnectionStringBuilder _connectionString = new SqlConnectionStringBuilder();
_connectionString.DataSource = #".\SQLEXPRESS";
_connectionString.InitialCatalog = "databaseName"; //add database name which created dynamically
_connectionString.IntegratedSecurity = true;
}
catch(Exception ex)
{
MessageBox.Show("Not able to create connection string. Error : " +ex);
}

Related

SQLCipher integration into Xamarin.Forms; SQLite Library doesn't support encryption exception

I am implementing SQLCipher into a Xamarin.Forms application. I thought everything was working until I noticed that the DB that was being created by the X.F. application was actually a SQLite3 DB w/o encryption or a password. After looking into it for a while, I haven't been able to find a solution. I am encountering an exception that says
System.InvalidOperationException: 'You specified a password in the connection string, but the native SQLite library you're using doesn't support encryption.'
I currently have 4 projects in this solution. The standard 3 in XamarinForms (Default PCL for cross platform stuff, Project.Android, and Project.iOS). In addition to those 3, I have a custom PCL that is labeled Project.Core. This PCL is responsible for all DataAccess since it implements the Repository Pattern, Unit Of Work, DbContext, etc.
In this 4th project, and within my DbContext.cs class, I have this:
// Added for more context
using System;
using System.IO;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Xamarin.Forms;
private SqliteConnection connection;
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
string connStr = Path.Combine(
path1: Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
path2: "App.db");
string passStr = deviceIdentifier;
string path = Path.GetDirectoryName(connStr);
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
// Check if db file exists
if (!File.Exists(connStr))
{
FileStream stream = File.Create(connStr);
stream.Close();
}
// DOCS => https://learn.microsoft.com/en-us/dotnet/standard/data/sqlite/encryption?tabs=netcore-cli
// => https://www.bricelam.net/2016/06/13/sqlite-encryption.html
var connectionString = new SqliteConnectionStringBuilder()
{
DataSource = connStr,
Mode = SqliteOpenMode.ReadWriteCreate,
Password = passStr
}.ToString();
// NOTE: THIS IS WHERE THE EXCEPTION IS THROWN!!!
// THE CODE BELOW THIS IS AN ALTERNATE ROUTE THAT DOENS'T WORK EITHER
**connection.Open();**
// This code doesn't throw anything, but it doesn't key the DB either
using (SqliteCommand command = connection.CreateCommand())
{
command.CommandText = "SELECT quote($password);";
command.Parameters.AddWithValue("$password", passStr);
string escapedPassword = (string)command.ExecuteScalar(); // Protects against SQL injection
command.CommandText = "PRAGMA key = " + escapedPassword /*+ ";"*/;
command.Parameters.Clear();
command.ExecuteNonQuery();
}
#if DEBUG
optionsBuilder.EnableSensitiveDataLogging();
#endif
optionsBuilder.UseSqlite(connection);
SQLitePCL.Batteries_V2.Init();
}
Through my research it appears there might be an issue with one of the SQLite/SQLCipher packages in this PCL (the PCL is targeting .NET Standard 2.0 for reference).
I currently have:
Microsoft.Data.Sqlite.Core 3.1.1 (w/ dependencies on Microsoft.Data.Sqlite.dll & SQLitePCLRaw.core 2.0.2)
SQLitePCLRaw.bundle_sqlcipher 1.1.14 (w dependencies on SQLitePCLRaw.core 2.0.2, SQLitePCLRaw.batteries_sqlcipher.dll, SQLitePCLRaw.batteries_v2.dll)
A couple of other things to note:
When viewing SQLitePCL namespace, it shows the package as being sqlitepclraw.bundle_e_sqlite3 instead of having a reference to sqlcipher.
\.nuget\packages\sqlitepclraw.bundle_e_sqlite3\2.0.2\lib\netstandard2.0\SQLitePCLRaw.batteries_v2.dll
I believe there may be an issue with that dependency, but I'm not sure and would appreciate any assistance!
Thanks in advance.
PS - Can provide more information as requested
Found a working solution.
After looking into the packages, I found that replacing the existing SQLitePCLRaw bundle package with SQLitePCLRaw.bundle_zetetic found here, resolved the issues connecting and maintaining an encrypted database.
Working code snippet is:
// StringBuilder here, and the SqliteConnection below are
// from the Microsoft.Data.Sqlite namespace v3.1.1
var connectionString = new SqliteConnectionStringBuilder()
{
DataSource = connStr,
Mode = SqliteOpenMode.ReadWriteCreate,
Password = passStr
}.ToString();
connection = new SqliteConnection(connectionString);
connection.Open();

SSIS C# Script Task Error

All, I'm using SQL 2014 and Visual Studio 2013.
I have a script task that is not firing. It's being read, but not working. This task creates tables and inserts data into them. I need to do this with a script task as there are 100's of TSV files and the fields may change month to month and it's a pain maintaining individual nodes for each table.
If you look at the code snippet, the message boxes (1) do fire, but the script errors right after - I believe at (2):
The error message is:
I think this error refers to variables that are not accessible in the task or are misspelled, etc. I've checked these Ad nauseam - don't think that's it.
Any help is greatly appreciated. Thank you.
The problem in your code is that you are creating an ADO.NET (C# standard) connection in your script code, but the base of this - DBconn connection manager - is an OLEDB connection manager. These two connections could not be casted into one another.
Suggestions:
If possible, create DBconn connection manager as an ADO.NET. Then your code should work.
In case you have to keep DBconn as an OLEDB connection manager, you have to create a SqlConnection connection in script task based on DBconn. I have done that building connection string for ADO.NET from OLEDB conn string and creating a new SqlConnection with that connection string.
Below is a code sample for function generating Connection String.
using RuntimeWrapper = Microsoft.SqlServer.Dts.Runtime.Wrapper;
using System.Data.OleDb;
using System.Data.SqlClient;
using Microsoft.SqlServer.Dts.Runtime;
static string Get_ManagedConnString(string Src_Name, ConnectionManager CM)
{
if (CM.CreationName != "OLEDB")
throw new Exception(string.Format("Cannot get Conn String from non-OLEDB Conn manager {0}", CM.Name));
RuntimeWrapper.IDTSConnectionManagerDatabaseParameters100 cmParams_Src = CM.InnerObject as RuntimeWrapper.IDTSConnectionManagerDatabaseParameters100;
OleDbConnection oledbConn_Src = cmParams_Src.GetConnectionForSchema() as OleDbConnection;
OleDbConnectionStringBuilder oledbCSBuilder_Src = new OleDbConnectionStringBuilder(oledbConn_Src.ConnectionString);
SqlConnectionStringBuilder sqlCSBuilder_Src = new SqlConnectionStringBuilder();
sqlCSBuilder_Src.DataSource = oledbCSBuilder_Src["Data Source"].ToString();
sqlCSBuilder_Src.InitialCatalog = oledbCSBuilder_Src["Initial Catalog"].ToString();
if (oledbCSBuilder_Src["integrated security"].ToString() == "SSPI")
{
sqlCSBuilder_Src.IntegratedSecurity = true;
}
else
{
sqlCSBuilder_Src.UserID = oledbCSBuilder_Src["User ID"].ToString();
sqlCSBuilder_Src.Password = oledbCSBuilder_Src["Password"].ToString();
}
return sqlCSBuilder_Src.ConnectionString;
}

How to Protect My Configuration File

I am writing an SQL Server application in C# built in Visual Studio. It is a Windows Forms Application. The program will be installed on the network where users will run it.
The problem I am struggling with is how to manage the configuration file. It has the server username and password there for all to see. I tried Click Once and an encryption scheme but they both required the programs to run on the computer the program was running from. It failed when I tried to run it from a workstation. This is different from How do I avoid having the database password stored in plaintext in sourcecode? because all of those solutions either suggested using integrated security or machine based encryption. Neither of those options would work for me.
Any help would be deeply appreciated.
Don't store passwords in plain text. Period. Full stop.
You should take a cue from SQL Server. Yes, you can store usernames in passwords in plain text in a web/app.config. But for Production servers you never should. Instead for Production deployments you should have a config that uses Integrated Security. That allows for elevated access by accessing credentials which are handled securely by Windows rather than insecurely in a config file.
Similarly, you should use something like WindowsIdentity, or OpenId. Then you can pass around auth tokens in your code rather than storing credentials in plain text.
This is why software developers created multi-tier designs that include middleware services like web services. Web services can be hosted in IIS and the windows account and password can be configured into the Application Identity section of the application connection pool. Then the web.config connection string can be configured with trusted_connection=true. Configuring it this way uses the Windows Data Protection API to protect the identities.
If you mean data at app.config it is simple! You have to use these two classes:
EntityConnectionStringBuilder
https://msdn.microsoft.com/en-us/library/system.data.entityclient.entityconnectionstringbuilder(v=vs.110).aspx
And
SqlConnectionStringBuilder
https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnectionstringbuilder(v=vs.110).aspx
I learn it from this page: Programmatic Connection Strings in Entity Framework 6 It is very good guide. In any cases, That link didn't help you!? Just Google something like this:
C# define connection string at runtime
After you put all connection string inside your code, you can go and delete any sensitive data from connectionStrings tag of app.config file because your app will not use it anymore! Then compile your code again.
If you are using DB First in EF, then you can check this Guide too: How to set Connection String with Entity Framework
UPDATED:
I added two of my Classes that I manage and create connection string with them programmatic (Dynamic), One is belong to my Entity Framework project that I used SQL Server Compact Edition (SQL Server CE) and the second one belong to another Entity Framework Project That I used SQL Server Express 2014 with SQL Server authentication (used sa username). I will leave both method here in case anyone need them:
This belong to my SQL Server CE project:
public static string GetDBConnectionString(string dataParentPath = "")
{
EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
SqlCeConnectionStringBuilder sqlCEBuilder = new SqlCeConnectionStringBuilder();
if (string.IsNullOrEmpty(dataParentPath) == true)
dataParentPath = #"C:\MyDBFolder\CMS.sdf";
sqlCEBuilder.DataSource = dataParentPath;
sqlCEBuilder.Password = "12345687";
sqlCEBuilder.MaxDatabaseSize = 4090;
entityBuilder.Metadata = "res://*/CMS.csdl|res://*/CMS.ssdl|res://*/CMS.msl";
entityBuilder.ProviderConnectionString = sqlCEBuilder.ToString();
entityBuilder.Provider = "System.Data.SqlServerCe.4.0";
return entityBuilder.ToString();
}
This belongs to my SQL Server Express project with SQL Server authentication:
using System;
using System.Collections.Generic;
using System.Data.Entity.Core.EntityClient;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CMS
{
class mySettings
{
public static string GetDBConnectionString()
{
// **************************************************
// This is my "ConnectionString" from App.config file.
// <connectionStrings>
// <add name="CMSEntities"
// connectionString=
// "metadata=res://*/CMS.csdl|res://*/CMS.ssdl|res://*/CMS.msl
// ;provider=System.Data.SqlClient
// ;provider connection string=&quot
// ;data source=MY-PC\SQLEXPRESS
// ;initial catalog=CMS
// ;user id=sa
// ;password=12345687
// ;MultipleActiveResultSets=True
// ;App=EntityFramework
// ""
// providerName="System.Data.EntityClient" />
//</connectionStrings>
// **************************************************
string metaData = "res://*/CMS.csdl|res://*/CMS.ssdl|res://*/CMS.msl";
string providerName = "System.Data.SqlClient";
string dataSource = #"MY-PC\SQLEXPRESS";
string databaseName = "CMS"; // = InitialCatalog
string userID = "sa";
string password = "12345687";
string appName = "EntityFramework";
EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
SqlConnectionStringBuilder sqlBuilder = new SqlConnectionStringBuilder();
// = = = = = = = = = = = = = = = =
sqlBuilder.DataSource = dataSource;
sqlBuilder.InitialCatalog = databaseName;
sqlBuilder.MultipleActiveResultSets = true;
sqlBuilder.UserID = userID;
sqlBuilder.Password = password;
sqlBuilder.ApplicationName = appName;
// = = = = = = = = = = = = = = = =
entityBuilder.Provider = providerName;
entityBuilder.Metadata = metaData;
entityBuilder.ProviderConnectionString = sqlBuilder.ConnectionString;
return entityBuilder.ToString();
}
}
}
As you can see, My database in both project have same name "CMS" so its Entities will be named "CMSEntities". Now! you have to override its DbContext constructor. It is Important but easiest part! Better description than mine is from this page "http://www.cosairus.com/Blog/2015/3/10/programmatic-connection-strings-in-entity-framework-6":
Now your Entity Model extends from DbContext and DbContext provides a
constructor to pass in a Connection String, but your Entity Model does
not overload those constructors for you. In order to access the
constructor overload, you will need to create a new class partial for
your Entity Model database context in the same namespace as your
Entity Model with the required constructor signature. Pro Tip: be sure
to name the filename of the cs file a different name than the Entity
Model database context in the event that future generated code does
not overwrite your changes.
So I build a class at root of my Project, The class must be partial:
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CMS // Your Project Namespace
{
public partial class CMSEntities : DbContext
{
public CMSEntities(string connectionString)
: base(connectionString)
{
}
}
}
and Anytime I wanna access to my Database I will use this code:
using (CMSEntities db = new CMSEntities(CMSSettings.GetDBConnectionString()))
{
// Do your DB stuff here...
}
I hope It help you or others which I learn all of that from this site "stackoverflow" and users.
Good Luck

How to connect to SQL Server CE using ADO.NET

I have a EntityModel created from ADO.NET that connects to my database. I want to fill a DataGridview. For that I'm following this code:
using System.Data;
using System.Data.SqlServerCe;
using System.Windows.Forms;
namespace WindowsFormsApplication5
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
FillData();
}
void FillData()
{
// 1
// Open connection
using (SqlCeConnection c = new SqlCeConnection(
Properties.Settings.Default.DataConnectionString))
{
c.Open();
// 2
// Create new DataAdapter
using (SqlCeDataAdapter a = new SqlCeDataAdapter(
"SELECT * FROM Animals", c))
{
// 3
// Use DataAdapter to fill DataTable
DataTable t = new DataTable();
a.Fill(t);
// 4
// Render data onto the screen
dataGridView1.DataSource = t;
}
}
}
}
This code comes from a Web Page, so I'm trying to adapt it to my ADO.NET model. So, as I'm not sure where the Properties.Settings.Default.DataConnectionStringcomes from, I thought it was the connection string used to connect to my database, so, following my Entity Model, I wrote this to get the connection string:
SqlCeConnection c = new SqlCeConnection(db.Connection.ConnectionString);
Where db is my Entity Model created like this:
private dbEntities db = new dbEntities();
But this db.Connection.ConnectionString returns this: "name= dbEntities", so I changed it to db.Connection.DataSource, that returns this string:
"C:\\Users\\user\\Documents\\Visual Studio 2010\\Projects\\ProjectName\\MySQLProject\\bin\\Debug\\db.sdf" string
But it says that the string format is not adjusted (obviously...). I'm using SQL Server, but I'm not sure how to get that connection :(
The Properties.Settings.Default.DataConnectionString says this:
Properties.Settings.Default.dbConnectionString 'System.Windows.Forms.PropertyStore'
does not contain a definition for 'Settings' and no extension method 'Settings' accepting a first argument of type 'System.Windows.Forms.PropertyStore' could be found (are you missing a using directive or an assembly reference?)
The message does not mean the connection string is in wrong format! Is says that there are no settings in your project.
Are you sure that you created a respective setting? To edit them, double click the "Properties" entry in your project, then switch to the "Settings" tab. If there's no entry dbConnectionString, create one.

Create .mdf/.sdf database dynamically

How can I with "code" create a new .mdf/.sdf database?
I've tried this:
http://support.microsoft.com/kb/307283
All it does is fail on the ConnectionString. Since I have no connection to a file that exists before I create it, how can I only connect to the SQL Express Server just to create a mdf/sdf database?
I want to be able to just connect to the server and create the file, from there it probably will be easier to create the tables and such.
Any suggestions?
public static void CreateSqlDatabase(string filename)
{
string databaseName = System.IO.Path.GetFileNameWithoutExtension(filename);
using (var connection = new System.Data.SqlClient.SqlConnection(
"Data Source=.\\sqlexpress;Initial Catalog=tempdb; Integrated Security=true;User Instance=True;"))
{
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText =
String.Format("CREATE DATABASE {0} ON PRIMARY (NAME={0}, FILENAME='{1}')", databaseName, filename);
command.ExecuteNonQuery();
command.CommandText =
String.Format("EXEC sp_detach_db '{0}', 'true'", databaseName);
command.ExecuteNonQuery();
}
}
}
Change Catalog=tempdb to Catalog=master, its good worked
Sample use:
var filename = System.IO.Path.Combine("D:\\", "testdb.mdf");
if (!System.IO.File.Exists(filename))
{
CreateSqlDatabase(filename);
}
Regarding .sdf files (SQL Server CE), you can use the SqlCeEngine class to create a new database, as described in this MSDN article.
Create .sdf database
using System.Data.SqlServerCe;
using System.IO;
string folderPath="D:\\Compact_DB"
string connectionString;
string fileName =folderPath+"\\School.sdf";
string password = "12345";
if (File.Exists(fileName))
{
File.Delete(fileName);
}
connectionString = string.Format("DataSource=\"{0}\"; Password='{1}'", fileName, password);
SqlCeEngine obj_ceEngine = new SqlCeEngine(connectionString);
obj_ceEngine.CreateDatabase();
Make sure you have a valid connection string.
The database/catalog that you need must be set to a valid database, usually this can be the "master" which is always available and since you will be using master to create a database.
If you need to create a database from scratch programmatically i normal go into the SQL Server Management Studio and create it through the gui in a first step. But instead of clicking on the OK button in the bottom right, i click on the Script button in the top toolbar. This will give me a complete sql script for creating the database i'd like to have. Then i can alter the script and change the parts i'd like dynamically.
I suppose the problem is in the ConnectionString. It should point to the valid instance of the master db (as in the article you refer to). Make sure it is correct, and it should work.
Use a connectionString with InitialCatalog = master. Since only master has default access to create a database.

Categories

Resources