Entity Framework - connection properties from user - entity-framework

I'm creating application, that will be able to connect to any database which user wishes. I'm trying to connect, but I'm always getting exception about connection string. My code looks like:
public string GetConnectionString(string userName, string password, string database, string server)
{
return string.Format(
#"metadata=res://*/Data.Database.csdl|res://*/Data.Database.ssdl|res://*/Data.Database.msl;provider=System.Data.SqlClient;provider connection string="data source={0};initial catalog={1};persist security info=True;user id={2};password={3};multipleactiveresultsets=True;App=EntityFramework"",
server,
database,
userName,
password);
}
and
DatabaseContext context = new DatabaseContext(GetConnectionString(UserName, Password, DatabaseName, ServerName));
What is wrong with my connection string? I just copied it from app.config file.

Answer is on this page: http://msdn.microsoft.com/en-us/library/vstudio/bb738533(v=vs.100).aspx. They are creating SqlConnectionStringBuilder and after that EntityConnectionStringBuilder which produces proper Entity Framework connection string.

Related

Npgsql Provide Client Certificate and Key

I am trying to formulate a connection to a PGSQL server that requires both a client certificate and key to operate.
First, I can verify connections to the Postgres database using SQLGate work. Provide host, User, password, port, database and mark Use SSL, then under SSL provide the Certificate and Key. The connection does not operate without either of those items. Using NPGSQL, I provide all but the key as for some reason NpgsqlConnectionStringBuilder does not contain a definition for some sort of client key.
var connectionString = new NpgsqlConnectionStringBuilder();
connectionString.Host = rInfo.Host;
int portNumber = 5432;
int.TryParse(rInfo.Port, out portNumber);
connectionString.Port = portNumber;
connectionString.Database = rInfo.dbName;
connectionString.Username = rInfo.Username;
connectionString.Password = rInfo.Password;
connectionString.SslMode = SslMode.Prefer;
connectionString.TrustServerCertificate = true;
connectionString.ClientCertificate = rInfo.CertFilePath;
//Poke the database, see if we can get in.
try
{
NpgsqlConnection npgsqlConnection = new NpgsqlConnection(connectionString.ToString());
npgsqlConnection.ProvideClientCertificatesCallback += provideCertificates;
npgsqlConnection.UserCertificateValidationCallback += validateCertificates;
npgsqlConnection.Open();
npgsqlConnection.Close();
return connectionString.ToString();
}
The exception is:
Error 28000 : connection requires a valid client certificate
Which is to be expected since I'm not providing the key anywhere. I have tried forcing the key to be added to the connection string via guessing:
connectionString.Add(new KeyValuePair<string, object?>("Client Key", rInfo.KeyFilePath));
But that's unrecognized. Libpq's PG Connect documentation labels it as sslkey, but that comes back as unrecognized as well. My best guess is using ProvideClientCertificatesCallback callback to provide the certificate, but I don't know how to have it pair with a key since it's just asking for an X509CertificateCollection.
The previous tool we were using was provided by Devart, but we have lost the license. We also will be connecting to a range of databases (with the same schema) instead of just one.
What are my options?

Use Entity Framework 6 Migrations with SqlConnection with AccessToken

I am trying to use EntityFramework 6 Migrations in conjunction with Azure Databases. I am using a SqlConnection with AccessToken to Connect to the Azure Database and Migrate.
public class MasterDbContext : DbContext
{
//...
public MasterDbContext(SqlConnection connection)
: base(connection,true)
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MasterDbContext, Migrations.Configuration>(true));
}
//...
}
public async Task SeedMasterDatabaseAsync(string connectionString)
{
SqlConnection conn = new SqlConnection(connectionString)
{
AccessToken = "xyc"
};
using (var dbcontext = new MasterDbContext(conn))
{
dbcontext.Database.Initialize(false);
}
}
I am receiving the followoing exception:
Unhandled Exception: System.InvalidOperationException: This operation requires a connection to the 'master' database. Unable to create a connection to the 'master' database because the original database connection has been opened and credentials have been removed from the connection string. Supply an unopened connection. ---> System.Data.SqlClient.SqlException: Login failed for user ''.
The exception message implies that the DBMigrator is not useing the SQL Connection but tries to create a new Connection from the Connectionstring.
This is my Connectionstring:
<add name="MasterDbContext" connectionString="Server=foo;Persist Security Info=True;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" providerName="System.Data.SqlClient" />
The question is, are AccessToken supported in EF6.3 Migrations in conjunction with Azure Databases? Or is this an permission Issue on master database? Any workaround if AccessToken are a mandatory requirement?

How to create and connect to a test database with Entity Framework

I have a Web API project accessing a database file in its App_Data folder. The database is created using EF Migrations.
I have some integration tests to confirm data structures and queries. They just create a Web API controller and use it to perform queries. My Test Project has an App.config file, which currently has an absolute path to the *.mdf database file (in the web api project).
This is a problem because a) I am doing my tests on the application database, and b) I have an absolute path in my App.config file.
I would like to create a test database in the test project.
Is there some way I can get Migrations to create another database (with a different Seed method) in the Test Project?
In the Web Api project's Web.config connection string we use |DataDirectory| to specify the location of the database. Is there an equivalent in a test project's App.config?
Failing all that, is there some way I can point the test project's connection string to the application db without using an absolute path?
My solution is to have a static DbManager class that does a Setup(), which I will run from the [ClassInitialize] method of the database testing classes. Setup()will:
Change the connection string according to the current AppDomain.CurrentDomain.BaseDirectory (so no longer an absolute path in App.config).
Use other AppSettings from App.config to determine which database to use, which test data set to use, and whether or not to drop and recreate the database.
Some code:
public static class DbManager
{
private static string ErrorMsg { get; set; }
private static ApplicationDbContext _db;
private static readonly Random Rdm = new Random();
public static void SetupDb()
{
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
bool refreshDb = Convert.ToBoolean(ConfigurationManager.AppSettings["RefreshDbInTestClassInitialization"]);
string dataSet = ConfigurationManager.AppSettings["DataSetToAddForEachTestClass"];
string dbName = ConfigurationManager.AppSettings["testDatabaseName"];
var connectionStr = config.ConnectionStrings
.ConnectionStrings["DefaultConnection"].ConnectionString
.Replace("{dbPath}", Path.Combine(AppDomain.CurrentDomain.BaseDirectory, (dbName + ".mdf")))
.Replace("{dbName}", dbName);
config.AppSettings.SectionInformation.ForceSave = true;
config.ConnectionStrings.ConnectionStrings["DefaultConnection"].ConnectionString = connectionStr;
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("connectionStrings");
if (refreshDb)
{
Database.Delete(connectionStr);
AddDataSet(dataSet, true);
}
}
// AddDataSet() creates a DbContext object and generates test data.
}
So the connection string in App.config looks like this:
connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename={dbPath};Initial Catalog={dbName};Integrated Security=True"
Then App.config AppSettings section has these extra key value pairs:
<add key ="RefreshDbInTestClassInitialization" value ="true"/>
<add key="DataSetToAddForEachTestClass" value="Large"/> <!--Possible values: Large, Small-->
<add key="testDatabaseName" value="testDb"/>

Sql Azure Connection String error

I am trying to connect to Sql Azure use the ADO.net connection still provided by the portal. It is of the format
var connectionstring =
"Server=tcp:abcdefghij.database.windows.net,1433;Database=[myDatabase];User ID=[myName]#abcdefghij;Password=[]myPassWord;Trusted_Connection=False;Encrypt=True;Connection Timeout=30;"
When I pass this connection string to the DbContext constructor it falls over. The error message is
"The type initializer for 'System.Data.Entity.ModelConfiguration.Utilities.TypeExtensions' threw an exception."
Any ideas what the problem can be?
Thanks
Martin

can't change connection string (ODP, Oracle, Linq to Entities)

I have a App.config connection string that connects me to my database just fine:
<add name="SFEntities" connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=Oracle.DataAccess.Client;provider connection string="DATA SOURCE=micahs_poc_dev_server.kci;PASSWORD=kierkegaard;PERSIST SECURITY INFO=True;USER ID=KIERKEGAARD"" providerName="System.Data.EntityClient" />
I am using an ODP reference in conjunction with an ADO.NET / Linq to Entities approach.
The trouble comes when I want to connect to a different database (with the same schema) on our network.
<add name="SFEntities" connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=Oracle.DataAccess.Client;provider connection string="DATA SOURCE=QA_ETL_TEST_SERVER.COM;PASSWORD=bigshotpassword;PERSIST SECURITY INFO=True;USER ID=CoolidgeCalvin"" providerName="System.Data.EntityClient" />
When I just change the name of the server I get this error:
ORA-00942: table or view does not exist
I can actually run several lines of code before it throws an exception:
using (SFEntities ctx1 = new SFEntities())
{
var ds = ctx1.Connection.DataSource; // debugger: QA_ETL_TEST_SERVER.COM
var db = ctx1.Connection.Database;
var dstate = ctx1.Connection.State;
var dsite = ctx1.Connection.Site;
ctx1.Connection.Open();
SF_CHANGE_ORDER cotest = new SF_CHANGE_ORDER();
cotest.DELETE_FLAG = "D";
var result = (from cp in ctx1.SF_CLIENT_PROJECT
select cp).ToList(); // <--- error here!
I also tried changing the format to this:
<add name="SFEntities" connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=Oracle.DataAccess.Client;provider connection string="DATA SOURCE=(DESCRIPTION =(ADDRESS=(PROTOCOL=TCP)(HOST=155.32.75.11)(PORT=65550))(ADDRESS=(PROTOCOL=TCP)(HOST=155.32.75.11)(PORT=65550))(CONNECT_DATA=(SERVICE_NAME=QA_ETL_TEST_SERVER.COM)(FAILOVER_MODE=(TYPE=SELECT)(METHOD=BASIC)(RETRIES=180)(DELAY=5))));PASSWORD=bigshotpassword;PERSIST SECURITY INFO=True;USER ID=CoolidgeCalvin"" providerName="System.Data.EntityClient" />
Which basically mirrors the TNS entry I have for this server. I still get the 'does not exist' error.
If I make the server name something goofy I get a TNS error saying that server isn't recognized. So I am pretty sure it is picking up the server name I want and checking to see it is there.
I don't think it is a table permissions/creation issue because I can query them just fine on both databases from the same machine with the same credentials (and same TNS file).
[note: I changed the server/user/pw in the strings]
[edit: tried bringing up fiddler, but I didn't see any messages pass through]
Ah ... VisualStudio tucks away the schema name in the Model .edmx file. To make it work you have to somehow open the model file (use notepad or search all documents in the project) and manually change the schema name. Boo!