I am using an Oracle DB with EF 6 code first.
And did custom encryption on connection string.
Connection string stores in separate config file "connstring.config": There is a clear connection string without encryption
<?xml version="1.0" encoding="utf-8" ?>
<connectionStrings>
<add name="MyConnString" connectionString="Data Source=MySource;User ID=UserID;Password=Password;PERSIST SECURITY INFO=True;"
providerName="Oracle.ManagedDataAccess.Client" />
</connectionStrings>
Data sources in web.config file.
MyDbcontext:
public static string GetConnectionString()
{
string encodedConnStr = ConfigurationManager.ConnectionStrings["MyConnString"].ConnectionString.ToString();
string result = Crypto.Decrypt(encodedConnStr);
return result;
}
public MyDbContext() : base(GetConnectionString()){}
And when I run application I am getting Server Error : Unable to complete operation. The supplied SqlConnection does not specify an initial catalog or AttachDBFileName.
How can I solve this?
Because you are passing the connection string directly to the DbContext constructor you need to provide it with a database provider otherwise it does not know what database type it is creating connections for. The easiest thing to do is to alter the connection string, you can do this post encryption in your static method or in your encrypted connection string. Based on your connection above I believe oracle.manageddataaccess.client is the correct provider but test it and see.
Provider=oracle.manageddataaccess.client;Data Source=MySource;User ID=UserID;Password=Password;PERSIST SECURITY INFO=True
You can also try thing according to this other answer I found on SO: How to set manually an Oracle Connection String in a DbContext
class MyDbContext: DbContext
{
public MyDbContext() : base(new OracleConnection(GetConnectionString()){}
...
}
If you are still experiencing problems update your question with just the relevant parts: that you cannot instantiate a DbContext instance when you manually provide a connection string. As it is written now it is very easy to make the assumption that your issue was with the encryption/decryption but these are irrelevant to the actual problem.
It was solved by setting defaultConnectionFactory to
Oracle.ManagedDataAccess.EntityFramework.OracleConnectionFactory, Oracle.ManagedDataAccess.EntityFramework
Related
I have multiple projects being hosted in IIS. These all share a database, which is called using EF6. I want to be able to use a shared connection string config file which I can reference from each of the other projects' web.config. This way, I'm able to manage any chances to the connection string from a single location. From what I've found online, I'm trying to accomplish this through a Virtual Directory and the configSource attribute for the connectionString.
IIS structure
-VirtualDirectory (mapped to /DbConfigFile)
-WebApp 1
-WebApp 2
-WebApp 3
WebApps' Web.config connectionString sections
<connectionStrings configSource="/DbConfigFile/testDB.config"></connectionStrings>
The external config file (testDB.config) containing the connectionString needed by all applications.
<connectionStrings>
<add name="TestDBEntities" connectionString="metadata=res://*/TestDB.csdl|res://*/TestDB.ssdl|res://*/TestDB.msl;provider=System.Data.SqlClient;provider connection string="data source=TestDB;initial catalog=VBODashboard;persist security info=True;user id=Test;password=Test;MultipleActiveResultSets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
</connectionStrings>
I've tried various paths in the configSource attribute with no luck (~/DbConfigFile/testDB.config, testDB.config). How would I access this file? Or is there a better way to accomplish this?
I ended up going with one of mason's suggestions and creating a custom configuration file. That let me to research finding out that a connection string can be specified through code when initializing the context. I then navigated through the XML file through code and extracted the connection string value. :
public partial class TestDBEntities : DbContext
{
public TestDBEntities()
: base(<calling code to get connection string> , true)
{
}
...
}
I've been spinning my wheels on this for awhile now and haven't been able to find anything substantial on the topic.
I've implemented an MVC 6 project that is utilizing the Identity Framework 2 and Entity Framework 6. The application works fine with a local database being used as my identity repository. On the first connection, the Entity Framework creates the identity tables based on my identity model classes. I built it based off of a project from this book. The chapters on using Identity and all of the online samples I find don't cover pointing the entity framework to a remote database.
Here are my connection strings I've experimented with...
Local database connection string. Project works fine.
<add name="IdentityDb" connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\IdentityDb.mdf;Integrated Security=True" providerName="System.Data.SqlClient" />
Failed approach 1. I based this off of other connection strings from my other projects. I removed the meta data parameters because when it comes to my understanding, this points to the edmx file but I don't have one since I'm taking a code first approach and letting identity and the entity frameworks build the database. I'm wondering if I'm missing something here because I've always taken a database first approach until now.
<add name="IdentityDb" connectionString="provider=System.Data.SqlClient;provider connection string="data source=****;initial catalog=IdentityTest;Uid=*****;Pwd=*****;integrated security=False;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
Returned exception details. The metadata keyword is missing.
System.ArgumentException: Some required information is missing from the connection string. The 'metadata' keyword is always required.
Failed approach 2. I built an empty Identity.edmx file thinking this must be where all of the metadata is stored and maybe the entity framework will update it and have it's required resources once the app connects to the database the first time.
<add name="IdentityDb" connectionString="metadata=res://*/Identity.csdl|res://*/Identity.ssdl|res://*/Identity.msl;provider=System.Data.SqlClient;provider connection string="data source=****;initial catalog=IdentityTest;Uid=****;Pwd=****;integrated security=False;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
Returned exception detail. The meta data is missing.
System.Data.Entity.Core.MetadataException: Unable to load the specified metadata resource.
Last failed approach. I found a lot of online sources where people simply changed the metadata parameters to "res://*". I'm guessing this is some kind of wildcard that would locate the metadata resources if they existed...
<add name="IdentityDb" connectionString="metadata=res://*;provider=System.Data.SqlClient;provider connection string="data source=****;initial catalog=IdentityTest;Uid=****;Pwd=****;integrated security=False;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
Returned exception details (With a identity.edmx file in the project)
System.NotSupportedException: Model compatibility cannot be checked because the DbContext instance was not created using Code First patterns. DbContext instances created from an ObjectContext or using an EDMX file cannot be checked for compatibility.
Returned exception details (Without an identity.edmx file in the project)
System.ArgumentException: Argument 'xmlReader' is not valid. A minimum of one .ssdl artifact must be supplied
My database context class
public class AppIdentityDbContext : IdentityDbContext<AppUser>
{
public AppIdentityDbContext() : base("name=IdentityDb") { }
static AppIdentityDbContext()
{
// Seeds the database when the schema is first created through the Entity Framework.
Database.SetInitializer<AppIdentityDbContext>(new IdentityDbInit());
}
// OWIN uses this method to create instances of this class when needed.
public static AppIdentityDbContext Create()
{
return new AppIdentityDbContext();
}
public System.Data.Entity.DbSet<UAM.Models.Identity.AppRole> IdentityRoles { get; set; }
}
// Seed class for initially populating the identity database.
public class IdentityDbInit : DropCreateDatabaseIfModelChanges<AppIdentityDbContext>
{
protected override void Seed(AppIdentityDbContext context)
{
PerformInitialSetup(context);
base.Seed(context);
}
public void PerformInitialSetup(AppIdentityDbContext context)
{
// Initial database configuration
}
}
Any help or insight would be much appreciated. What is the correct approach for doing this? Is there something that I need to do when I transition from using a local database to a remote one? Let me know if I should provide anymore code samples. I'm fairly new to MVC and am currently building this module so that I can use it for a few enterprise applications that I'll be developing this year.
You need to specify providerName="System.Data.SqlClient" instead of providerName="System.Data.EntityClient"
For Example
<add name="IdentityDb" connectionString="Data Source=*******;Database=IdentityTest;Integrated Security=false;User ID=**;Password=******;" providerName="System.Data.SqlClient"/>
This is the connection string I use and it worked without an issue.
<add name="InventoryEntities"
connectionString="metadata=res://*/Entities.csdl|res://*/Entities.ssdl|res://*/Entities.msl;provider=System.Data.SqlClient;provider connection string="data source=.\sqlinstance;initial catalog=DBName;persist security info=True;user id=UID;password=PWD;MultipleActiveResultSets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
The tool generated this for me (I didn't need to do anything custom to the connection string) so maybe you can delete and let the too re-add it? (I think it does that)?
Also, you didn't rename the EF files at all did you? If you did, you would have to update the connection string to match.
I have a connection string in my web.config file like this
<add name="ModelDbContext"
connectionString="metadata=res://*/Models.DizlyModel.csdl|res://*/Models.DizlyModel.ssdl|res://*/Models.DizlyModel.msl;provider=System.Data.SqlClient;provider connection string="data source={Server},1433;initial catalog=Dizlybeta;user id={id};Password={Password};MultipleActiveResultSets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
but then I go to my hosted azure website and place this as connection
And then I replace the hidden security with
metadata=res://*/Models.DizlyModel.csdl|res://*/Models.DizlyModel.ssdl|res://*/Models.DizlyModel.msl;provider=System.Data.SqlClient;provider connection string="data source={Server},1433;initial catalog=Dizlybeta;user id={id};Password={Password};MultipleActiveResultSets=True;App=EntityFramework"
but it still doesn't work, can anyone help me with how to place the right connection string in the website configuration?
Something to try:
Use a SqlClient connection string instead of an EntityClient connection string.
In that case, you'll probably need to pass the name of the connection string to the DbConext constructor, which you can do in one place like:
public MyDbContext : base("sqlClientConnectionStringName")
{
}
You might also need to ensure a SqlClient provider exists. Check the docs for more.
I have modified the web.config connection string. However, during debug, I still see the old connection string.
So, I have commented (and deleted) out the old connection string but, and added a new connection resource via server explorer. On testing the connection via wizard on the left panel in server explorer- it says connected.
After following this wizard, when I visit the web.config I dont see the new connection string.
Question: I suspect, I am not following the steps to add a connection string -
how can I add or update the connection string from the designer (in the designer properties panel, edit is greyed out, output type is build to assembly, and right clicking only gives me options to add entities etc, deleting the string and running the app, doesn't prompt for connection string wizard)
Below is the string -
<connectionStrings><add name="MaintRecordsDB_v1" connectionString="metadata=res://*/Models.DB.Model.csdl|res://*/Models.DB.Model.ssdl|res://*/Models.DB.Model.msl;provider=System.Data.SqlClient;provider connection string="data source=xxx.sample.net;initial catalog=MainDB;user id=maintRoot;password=hidden;multipleactiveresultsets=True;application name=EntityFramework"" providerName="System.Data.EntityClient" /><add name="MainDBentities" connectionString="metadata=res://*/Models.DB.Model.csdl|res://*/Models.DB.Model.ssdl|res://*/Models.DB.Model.msl;provider=System.Data.SqlClient;provider connection string="data source=windflower.arvixe.com;initial catalog=MX_Dashboard;user id=maintRoot;password=hidden;multipleactiveresultsets=True;application name=EntityFramework"" providerName="System.Data.EntityClient" /></connectionStrings>
Edit Question 2: How can I add another EF connection string for e.g. MaintDB2 using designer, and where do I update to this manually.
Without knowing what your context class looks like, say your DbContext class, if it was generated and assuming it's partial, you could try to add another partial class part to it with a constructor that takes a named connection string as an argument.
First add a named connection to your app.config/web.config:
<connectionStrings>
...
<add name="MyOtherConnection" connectionString="metadata=res://*/blahblahblah;provider=System.Data.SqlClient;provider connection string="Data Source=ABunchOfOtherStuff;"
providerName="System.Data.EntityClient" />
</connectionStrings>
Then add a matching partial class in another (non-generated) file with a constructor to take a connection string name:
// the class name must match the name of your existing context
public partial class MyContext : DbContext
{
public MyContext(string connectionStringName) : base("name=" + connectionStringName)
{
}
}
Then use your context by passing in the name of the connection string, demonstrated by some useless code:
// ...
using (var context = new MyContext("MyOtherConnection"))
{
var id = 1;
var collection = context.MyEntities.Where(a => a.ID == id).ToList();
}
In MVC several things are based on Convention. It prefers convention over configuration. By convention there should be a link between the two things. The class name of DbContext match the connection string for it to work correctly by convention
The class inheriting from DbContext say
public class DbPersonContext : DbContext
{ ... }
must have a connection string of the name Person
I have an entity in MVC 4 project and the connection string is placed in the web.config by the entity creation wizard.
I need to change this and assign the password to the connection string (which is stored outside the web.config) at run time.
How can I combine values outside the web.config with a string stored inside the web.config?
Or can I move the entity connection completely outside the web.config?
This is the existing entity connection string:
add name="MyEntities" connectionString="metadata=res://*/Models.NewUsers.csdl|res://*/Models.NewUsers.ssdl|res://*/Models.NewUsers.msl;provider=System.Data.SqlClient;provider connection string="data source=mydb;initial catalog=MyDatabase;persist security info=True;user id=sa;password=Mypassword;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" /></connectionStrings>
For 2, you can always pass a new connectionString (not from web.config) directly to the context when you create it:
string newCS = "add name=...";
var context = new MyEntities(newCS);
For 1, use EntityConnectionStringBuilder to parse an existing CS or build a new one.
A simple solution might be to use something based on:
string con = ConfigurationManager.ConnectionStrings["PerinatalDataEntities"].
ConnectionString;
con = con.replace("user id=sa", "user id=MyUser").
Replace("password=Mypassword","password=MyNewpassword")
I believe there is also a connection builder but I've never used it.