How to make a connection to a database via Massive?
There is a method in Massive for opening a connection, but it accepts name of a connection string. I want to give it the connection string. How can I do this?
In Massive code in Open() method is created DynamicModel and in DynamicModel constructor I found this line(Massive.cs 127 line):
ConnectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;
So that means you need to store connection string in configuration file and pass to Open method appropriated connection string name.
What you need is create overload methods to accept connection string. Here is an example:
public static DynamicModel Open(string connectionString, string providerName="System.Data.SqlClient")
{
dynamic dm = new DynamicModel(connectionString, providerName);
return dm;
}
public DynamicModel(string connectionString, string providerName ="System.Data.SqlClient", string tableName = "",
string primaryKeyField = "", string descriptorField = "")
{
TableName = tableName == "" ? this.GetType().Name : tableName;
PrimaryKeyField = string.IsNullOrEmpty(primaryKeyField) ? "ID" : primaryKeyField;
DescriptorField = descriptorField;
_factory = DbProviderFactories.GetFactory(providerName);
ConnectionString = connectionString;
}
Related
I have a ConnectionString and I want to pass it values (DataSource, Database, User ID, Password) with values from a .txt file and I need to read them, then pass them to the connectionString but I'm very confused how should I do this.
In my program I have a Helper Class to return the connectionString
public static class Helper
{
public static string ConnectionString(string name)
{
return ConfigurationManager.ConnectionStrings[name].ConnectionString;
}
}
This is how I call the connectionString so I can access the database data
using (IDbConnection connection = new System.Data.SqlClient.SqlConnection(Helper.ConnectionString("Hotel")))
{
connection.Execute($"INSERT INTO dbo.Registos_Cancelados(Nome, Telemovel, Data) VALUES(#Nome, #Telemovel, #Data)", new { Nome = nome, Telemovel = telemovel, Data = data });
}
I have a text file with the values
"DataSourceName"
"DataBaseName"
"User IDName"
"PasswordName"
And I want them in the connection string.
<connectionStrings>
<add name="Hotel" connectionString="DataSource="DataSourceName";Database="DatabaseName";User Id="UserIdName";Password="PasswordName""
providerName="System.Data.SqlClient" />
</connectionStrings>
You're using SqlClient, so: your best bet here is SqlConnectionStringBuilder:
var cb = new SqlConnectionStringBuilder(theBaseString);
cb.DataSource = dataSourceName;
cb.InitialCatalog = dataBaseName;
cb.UserID = userId;
cb.Password = password;
var connectionString = cb.ConnectionString;
If you don't have a template string (theBaseString), just use new SqlConnectionStringBuilder() instead.
The advantage of using SqlConnectionStringBuilder here is that it knows all about the escaping rules for non-trivial values, reserved characters, etc.
You can format your connection string like below to pass the necessary values like dbname later.
<connectionStrings>
<add name="Hotel" connectionString="DataSource={0};Database={1};User Id={2};Password={3}"
providerName="System.Data.SqlClient" />
</connectionStrings>
After that in your Helper class, return the formatted connection string with the values that you read from txt file.
public static string ConnectionString(string name)
{
var dataSourceName = "...";
var dbName = "...";
var userId = "...";
var password = "...";
var connectionString = ConfigurationManager.ConnectionStrings[name].ConnectionString;
return string.Format(connectionString, dataSourceName, dbName, userId, password);
}
I have query to dynamically create database.
private void ExecuteNonQuery(string sql)
{
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
SqlCommand command = connection.CreateCommand();
command.CommandText = sql;
command.ExecuteNonQuery();
}
}
private void CreateDatabase(string databaseName)
{
try
{
ExecuteNonQuery($"CREATE DATABASE {databaseName}");
}
catch (Exception e)
{
throw new Exception($"Can't create database '{databaseName}'");
}
}
Database will be created using my existing connection , But I need to create connection string for this new database to run migration and for various other purposes.
How is it possible ?
Update
Its actually for purpose where users can fill a form to create a new database where they can give their existing connection string or if they don't have one in hand we build it for them
use this function to get a connection to the new database:
private SqlConnection NewDatebaseConnection(string databaseName)
{
SqlConnection connection = new SqlConnection(_connectionString);
connection.ChangeDatabase(databaseName);
return SqlConnection;
}
To save new connection, you can use ConnectionStringBuilder with existing connection, change the name of database and save it to app.config.
1.Helper method to get connection string:
string GetConnectionString(string name) =>
ConfigurationManager.ConnectionStrings[name].ConnectionString;
2.Helper method which saves new connection string to app.config:
void CreateNewConnectionString(string baseName, string newName, string newDatabaseName)
{
// Get the connection string a new connection will be based on
string baseConnString =
ConfigurationManager.ConnectionStrings[baseName].ConnectionString;
// For simplicity of manipulations with connection strings,
// we use SqlConnectionStringBuilder, passing it an existing connection string
var connBuilder = new SqlConnectionStringBuilder(baseConnString);
// Change existing database name to the new database name
connBuilder.InitialCatalog = newDatabaseName;
// Create new settings, holding our new connection string
var newConnection = new ConnectionStringSettings(newName, connBuilder.ToString());
// Save new connection string
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.ConnectionStrings.ConnectionStrings.Add(newConnection);
config.Save(ConfigurationSaveMode.Modified);
}
3.Usage
private void CreateDatabase(string databaseName)
{
try
{
// Create database using "main" connection string
ExecuteNonQuery($"CREATE DATABASE {databaseName}", "main");
// Create new connection string "my_db" based on "main"
CreateNewConnectionString("main", "my_db", databaseName);
}
catch (Exception e)
{
throw new Exception($"Can't create database '{databaseName}'");
}
}
If you are using EF, you should have a context to work with, something like the following:
public class MyContext : DbContext
{
public MyContext():base("myConnectionStringName")
{
}
}
The constructor has a parameter that specifies connection name or a connection string. So, you can obtain a context for any connections string you want:
using (var db = new MyContext("connection_string_containing_new_db")
{
// do stuff with the context
}
You should consider using a factory that builds such contexts:
class MyContextFactory
{
MyContext CreateContextForDatabase(string dbName)
{
var builder = new SqlConnectionStringBuilder();
builder["Data Source"] = "server\\instance";
builder["integrated Security"] = true;
builder["Initial Catalog"] = dbName;
return new new MyContext(builder.ConnectionString);
}
}
The code uses SqlConnectionStringBuilder to construct (from scratch) the connection string. An alternative is to parse a static connection string using var builder = new SqlConnectionStringBuilder(staticConnectionString) and only change the Initial Catalog.
I've a very simple class that I've added method GetConnectionString(). After adding it whenever any value is accesses from the Settings class it throws an exception The type initializer for 'NameSpace.Settings' threw an exception. As soon as I remove GetConnectionString() program works fine.
using System.Data.EntityClient;
using System.Data.SqlClient;
namespace CRM {
static class Settings {
public static bool userAuthenticated = false;
public static string userGroup = "";
public static Klienci currentlySelectedClient;
public static string sqlDataConnectionDetailsCRM = GetConnectionString();
public static string GetConnectionString() {
string connection = "";
SqlConnectionStringBuilder sqlBuilder = new SqlConnectionStringBuilder();
sqlBuilder.InitialCatalog = dbInitialCatalog;
sqlBuilder.DataSource = dbServer;
sqlBuilder.IntegratedSecurity = false;
sqlBuilder.UserID = dbUserName;
sqlBuilder.Password = dbPasswWord;
sqlBuilder.MultipleActiveResultSets = true;
EntityConnectionStringBuilder entity = new EntityConnectionStringBuilder();
entity.Metadata = #"res://*/Data.System.csdl|res://*/Data.System.ssdl|res://*/Data.System.msl";
entity.Provider = "System.Data.SqlClient";
entity.ProviderConnectionString = sqlBuilder.ToString();
connection = entity.ToString();
return connection;
}
}
}
If I comment out sqlBuilder and entity. It works fine..
public static string GetConnectionString() {
string connection = "";
SqlConnectionStringBuilder sqlBuilder = new SqlConnectionStringBuilder();
//sqlBuilder.InitialCatalog = dbInitialCatalog;
//sqlBuilder.DataSource = dbServer;
//sqlBuilder.IntegratedSecurity = false;
//sqlBuilder.UserID = dbUserName;
//sqlBuilder.Password = dbPasswWord;
//sqlBuilder.MultipleActiveResultSets = true;
EntityConnectionStringBuilder entity = new EntityConnectionStringBuilder();
//entity.Metadata = #"res://*/Data.System.csdl|res://*/Data.System.ssdl|res://*/Data.System.msl";
//entity.Provider = "System.Data.SqlClient";
//entity.ProviderConnectionString = sqlBuilder.ToString();
connection = entity.ToString();
return connection;
}
What's going on? It seems fine to me..
Edit:
InnerException:
exception = "System.ArgumentNullException: Value cannot be
null.\r\nParameter name: Initial Catalog\r\n at
System.Data.SqlClient.SqlConnectionStringBuilder.set_InitialCatalog(String
value)\r\n at CRM.Settings.GetConnectionString() in
C:\Projects\Project.C.S...
While public static string dbInitialCatalog = "BazaCRM"; is set in Settings class.
The order of the fields being initialized is not guaranteed. What's going on here is that the sqlDataConnectionDetailsCRM is being initialized before the dbInitialCatalog field.
If you change those other static fields to be const it should fix it.
Or a better way might be to just removed your public static field, and retrieve the connection string from the method, or you might also like to investigate the Lazy<T> class, and use that to build the connection string the first time it's needed.
According to your error the value of dbInitialCatalog seems to be null, so the connection string builder is throwing an error. Because this is inside the static constructor of a class, the type itself can't be loaded and the whole thing fails.
Have you tried manually supplying the connection string yourself?
How can I get the user and password from such a connectionString in the app.config with a .NET function?
Of course I could read that string and get the value after the ID= and Password=.
<connectionStrings>
<add name="MyConString" connectionString="Data Source=(local);Initial Catalog=MyDatabase;Persist Security Info=True;User ID=MyUsername Password=MyPassword;Connect providerName="System.Data.SqlClient"/>
</connectionStrings>
use the ConnectionBuilderClass
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder("Your connection string");
string password = builder.Password;
together with the
string connString = ConfigurationManager.ConnectionStrings["MyConString"].ConnectionString;
to achieve this.
If you need a more generic approach for parsing the connection string (one that doesn't deal with the specifics of one database provider) you can also use
System.Data.Common.DbConnectionStringBuilder
which is a base class for other classes like SqlConnectionStringBuilder etc.
You can create an instance of DbConnectionStringBuilder and in my case I needed to have one configurable connection string that I could get information from -- regardless of the database provider type. A few options if you need this flexibility -- you could create the appropriate ConnectionStringBuilder for your provider as others have suggested -- this would likely be required for most cases where provider-specific properties are needed.
Or if you want to read just a couple generic properties, you could use DbConnectionStringBuilder if you just need the user id and password for example.
This sample should work for ANY connection string that includes user id and password.
DbConnectionStringBuilder db = new DbConnectionStringBuilder();
db.ConnectionString = ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString;
var username = db["User Id"].ToString();
var password = db["Password"].ToString();
SqlConnectionStringBuilder con = new SqlConnectionStringBuilder(ConfigurationManager.ConnectionStrings["ConnString"].ConnectionString);
string myUser = con.UserID;
string myPass = con.Password;
var builder = new SqlConnectionStringBuilder(ConfigurationManager.ConnectionStrings["MyConString"].ConnectionString)
var user = builder.UserID;
var password = builder.Password;
You can get the connection string from the following
SqlConnectionStringBuilder yourconn = new SqlConnectionStringBuilder(ConfigurationManager.ConnectionStrings["ConnString"].ConnectionString);
string password = yourconn.Password;
You can then get the substring you are looking for .
Just to add a bit to Tomas Walek's answer.
This approach would work only if "User ID" in the connection string is capitalized correctly. Oracle provider accepted "User Id" OK, but SqlConnectionStringBuilder did not work.
public static class DbConnectionFactory
{
public static ConnectionStringSettings AppConnectionSettings = ConfigurationManager.ConnectionStrings["{A connection string name}"];
public static SqlConnectionStringBuilder AppConnBuilder = new SqlConnectionStringBuilder(AppConnectionSettings.ConnectionString);
public static string DbUserID
{
get
{
return AppConnBuilder.UserID;
}
set { }
}
}
add a reference to System.Configuration and then use:
using System.Configuration;
string MyDBConnection = ConfigurationManager.ConnectionStrings["MyDBConnection"].ConnectionString;
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(MyDBConnection);
string UserID = builder.UserID;
string Password = builder.Password;
string ServerName = builder.DataSource;
string DatabaseName = builder.InitialCatalog;
public static string GetConnectionSettings(string searchSetting )
{
var con = ConfigurationManager.ConnectionStrings["yourConnectionHere"].ConnectionString;
String[] myString = con.Split(';');
Dictionary<string, string> dict = new Dictionary<string, string>();
for (int i = 0; i < myString.Count(); i++)
{
String[] con3 = myString[i].Split('='); dict.Add(con3[0], con3[1]);
}
return dict[searchSetting];
}
for searchSetting you can use what you want "User Is" or password.
another way is to use regular expression (which I did), with a more forgiving pattern, to handle different ways a user id could be provided on the connection string:
public static string GetUserIdFromConnectionString(string connectionString)
{
return new Regex("USER\\s+ID\\=\\s*?(?<UserId>\\w+)",
RegexOptions.IgnoreCase)
.Match(connectionString)
.Groups["UserId"]
?.Value;
}
Extension method to get "User Id" from connectionString in DbConnection:
using System;
using System.Data.Common;
using System.Text.RegularExpressions;
namespace DemoProject.Helpers
{
public static class DbConnectionExtensions
{
public static string GetUserId(this DbConnection connection)
{
const string userIdPattern1 = "User[ ]*Id";
const string userIdPattern2 = "UID";
var connectionString = connection.ConnectionString;
foreach (var item in connectionString.Split(';'))
{
var index = item.IndexOf('=');
if (index == -1)
continue;
var property = item.Substring(0, index).Trim();
if (Regex.IsMatch(property, userIdPattern1, RegexOptions.IgnoreCase) ||
Regex.IsMatch(property, userIdPattern2, RegexOptions.IgnoreCase))
{
var userId = item.Substring(index + 1).Trim();
return userId;
}
}
throw new Exception("Couldn't find \"User Id\" in connectionString");
}
}
}
Example #1 of using:
using DemoProject.Helpers;
using Oracle.ManagedDataAccess.Client;
namespace DemoProject
{
class Program
{
static void Main(string[] args)
{
const string connectionString = "Data Source=(DESCRIPTION=" +
"(ADDRESS=(PROTOCOL=TCP)(HOST=oracle19c-vm)(PORT=1521))" +
"(CONNECT_DATA=(SERVICE_NAME=ORCLPDB1)));" +
"User Id=JOHN;" +
"Password=pwd123";
var connection = new OracleConnection(connectionString);
var userId = connection.GetUserId();
}
}
}
Example #2 of using:
using DemoProject.Helpers;
using Npgsql;
namespace DemoProject
{
class Program
{
static void Main(string[] args)
{
const string connectionString = "Server=postgre-vm;" +
"User Id=JOHN;" +
"Password=pwd123;" +
"Database=DEV1";
var connection = new NpgsqlConnection(connectionString);
var userId = connection.GetUserId();
}
}
}
Also you can add the 2nd extension method to get the password
var connString = ConfigurationManager.ConnectionStrings["MyConString"].ConnectionString;
var tokens = connString.Split(';');
string userId;
string password;
for(var i = 0; i < tokens.Length; i++) {
var token = tokens[i];
if(token.StartsWith("User ID"))
userId = token.Substring(token.IndexOf("=") + 1);
if(token.StartsWith("Password"))
password = token.Substring(token.IndexOf("=") + 1);
}
string connectionString = ConfigurationManager.ConnectionStrings["MyConString"].ConnectionString;
var tokens = connectionString.Split(';').Select(n => n.Split('=');
string userId = tokens.First(n => n[0].Equals("User ID").Select(n => n[1]);
string password = tokens.First(n => n[0].Equals("Password").Select(n => n[1]);
I have class application that uses ado.net to connect to Sqlite database. The application uses the db to store some data and the db may be changed at run time. The user may make backups of the db and change the location, but in this case i need to know how to change the connection string.
I have tried this code but it didn't work:
string conn =
#"metadata=res://*/KzDm.csdl|res://*/KzDm.ssdl|res://*/KzDm.msl;" +
#"provider=System.Data.SQLite;" +
#"provider connection string=" +
#""" +#"Data Source=" +
#"F:\My Own programs\KrarZara2\KZ\KZ\Kzdb.s3db" +
#""";
Entities ent = new
Entities(conn);
this error "Keyword not supported: 'data source'."
happen at this line
public Entities(string connectionString) : base(connectionString, "Entities")
i write that and it worked with me
EntityConnectionStringBuilder conn = new EntityConnectionStringBuilder();
conn.Metadata = #"res://*/KzDm.csdl|res://*/KzDm.ssdl|res://*/KzDm.msl";
conn.Provider = "System.Data.SQLite";
conn.ProviderConnectionString = #"data source=F:\My Own programs\KrarZara2\KZ\KZ\KrarDS.krar;Version=3;";
EntityConnection entity = new EntityConnection(conn.ConnectionString);
using (DmEnt ent = new DmEnt(entity))
{
var parcel = ent.Parcels.SingleOrDefault(d => d.id == 1);
var pparcc = ent.Parcels.Select(d => d.id == 2);
Parcel r = new Parcel();
r.ParcelNumber = "11ju";
r.Area = 8787;
ent.AddToParcels(r);
ent.SaveChanges();
}
Dm ent is the entity model in edmx ado.net
wrong line order, should be:
#""" +
#"Data Source=" +
I'd actually surprised that connection string works at all. In addition, it would be simpler to use string.Format to build this connection string:
var filename = #"F:\My Own programs\KrarZara2\KZ\KZ\Kzdb.s3db";
var connString = string.Format("Data Source={0};UseUTF16Encoding=True;", filename );
using( var conn = new SQLiteConnection( connString ) )
{
...
}
First, you would replace UseUTF16Encoding with the proper value for your setup. Second, note that the file path in the connection string is not surrounded by quotation marks.
If you are looking for a means to swap Sqlite data files at runtime you might look at this blog entry:
SQLite and Entity Framework 4
A summary of the solution is to parse the Entity framework connection string, change the data file and then reset it:
public static string RedirectedEntityFrameworkConnectionString(string originalConnectionString, string databaseFile, string password)
{
// Parse the Entity Framework connection string.
var connectionStringBuilder = new EntityConnectionStringBuilder(originalConnectionString);
if (connectionStringBuilder.Provider != "System.Data.SQLite")
{
throw new ArgumentException("Entity Framework connection string does not use System.Data.SQLite provider.");
}
// Parse the underlying provider (SQLite) connection string.
var providerConnectionStringBuilder = new SQLiteConnectionStringBuilder(connectionStringBuilder.ProviderConnectionString);
// Redirect to the specified database file, and apply encryption.
providerConnectionStringBuilder.DataSource = databaseFile;
providerConnectionStringBuilder.Password = password;
// Rebuild the Entity Framework connection string.
connectionStringBuilder.ProviderConnectionString = providerConnectionStringBuilder.ConnectionString;
return connectionStringBuilder.ConnectionString;
}
To use, you would do something like:
const string OriginalConnectionString = "..."; // (Copy out of app.config)
var connectionString = RedirectedEntityFrameworkConnectionString(OriginalConnectionString, myFileName, null);
using (var context = new MyEntities(connectionString))
{
...
}