We have a project with multiple DLLs. In each DLL, we connect to a database - always the same one for a client.
As a result, we now have 3 near-identical connection strings : one for our web site, one for ado.net, and one for telerik reporting :
<add name="BDConnectionString" connectionString="Data Source=localhost;Initial Catalog=DATABASE;Persist Security Info=True;User ID=USER;Password=PASSWORD; MultipleActiveResultSets=True;Pooling=True;Max Pool Size=500;" providerName="System.Data.SqlClient" />
<add name="CMS.Reporting.My.MySettings.BDConnectionString" connectionString="Data Source=localhost;Initial Catalog=DATABASE;Persist Security Info=True;User ID=USER;Password=PASSWORD" providerName="System.Data.SqlClient" />
<add name="KOPWebEntities" connectionString="metadata=res://*/Data.web.csdl|res://*/Data.web.ssdl|res://*/Data.web.msl;provider=System.Data.SqlClient;provider connection string="Data Source=localhost;Initial Catalog=DATABASE;Persist Security Info=True;User ID=USER;Password=PASSWORD;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
Now it's still manageable, but in the future, we will have more ADO.Net Entity Framework connections, so maybe 10 connection strings by client ?
Is there a way to say, "ok, for this connection string, use the value coming from here" instead of duplicating it ? At least for ADO.Net ?
Or is there a better way ?
Thanks
I noticed you mentioned Entity Framework. It is possible to create entity contexts with different SQL connections than the one defined in the application/web config. (I'd have to dig up the code). However, as far as the more general "have a connection string that actually references another connection string" question, I'd say, if you don't have the source, tough luck.
It'd probably be better if your DLLs didn't reference app/web config settings and, for the classes defined in there, you could pass in either the, the "application key" which has an associated value referencing a connection string, the SQL connection string itself, a SqlConnection instance, or some SqlConnection-Factory-Thing you make up.
Related
I am learning asp.net mvc 4 on top of entity framework. There is a project at work I took over and I am trying to centralize the connection credentials depending on the environment (dev, test, prod) the application is in.
Currently I have the connectionstring dynamic, but for some reason entity framework ignores the connection string initial Catalog setting.
<connectionStrings>
<add name="name1" connectionString="metadata=res://*/Model.csdl|res: //*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient;provider connection string="Data Source=001\;Initial Catalog=**;Integrated Security=False;User ID=**;Password=**;MultipleActiveResultSets=True;Application Name=EntityFramework"" providerName="System.Data.EntityClient" />
<add name="name2" connectionString="metadata=res://*/Entites.csdl|res://*/Entites.ssdl|res://*/Entites.msl;provider=System.Data.SqlClient;provider connection string="data source=001\;Persist Security Info=True;User ID=**;password=**;multipleactiveresultsets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
I have no idea what half of the stuff in the connectionString means, but it is the second connection string giving me troubles, "name2"
Running the debugger shows the base class that extends the ObjectContext called like so,
: base("name=name2", "name2")
I figured Initial Catalog was already set in the connectionstring, "name1" and that would transfer to the name2.. but for the heck of it I added the Initial Catalog to the second connection string and it still defaults to the wrong catalog. I am connecting to the same database server but we have a test and a production database..
What could be overriding this catalog setting and redirecting to the wrong database? When I run my code, I get an innerexception telling me the username (the test database username) doesn't have access to the production database, but I am not sure why the production database is being passed in.
Here is the exception:
The server principal "testuser" is not able to access the database "ProductionName" under the current security context.]
initializing ObjectContext
public Entities() : base("name=name2", "name2")
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
This is also in the web.config files:
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
Something else interesting I noticed. When I leave the Initial Catalog setting in on the "name2" connectionstring, and set to the test database, and all the credentials are correct, I get the original error as I posted. If I change the initial Catalog to the production name and leave the wrong credentials to log in, I get a log in failed error. Same if I change the credentials around and leave the test database in for the initial catalog. So it seems it's authenticating properly, but something else is a factor once the connection goes through?
For anyone else who stumbles across this problem. I finally figured it out. The other developer was referring to the production database explicitly in all of the stored procedures. I took out all the references and left the implicit call using the "use" statement that was injected implicitly during the export/import process..
Example:
USE [TestDatabase] <---- this goes at top of procedure
Here was an explicit call to the production database:
FROM [productionDB].[dbo].[Table] table
just make it an implicit call like so:
FROM [dbo].[Table] table
If my solution is not the answer for you, I also stumbled across this bug in sql server 2008:
https://connect.microsoft.com/SQLServer/feedback/details/354291/the-server-principal-is-not-able-to-access-the-database-under-the-current-security-context-microsoft-sql-server-error-916
Can anyone suggest how I could programatically switch debug and live connection strings?
I've seen other people have passed an EntityConnection to the constructor from the controller like this :
private XYZDatabase db = new XYZDatabase(ConfigurationManager.
ConnectionStrings["XYZDatabase-TEST"].ConnectionString);
but it still requires manually changing it? is there a way to use
System.Net.Dns.GetHostName() or similar
to switch it automatically?
Thanks
Ayende has a post that addresses this issue.
http://ayende.com/blog/135169/frictionless-development-web-config-and-connection-strings
In my software I just have 2 connection strings of the same name in my app.config and comment/uncomment to switch between configurations.
Another method is that you could create a static property in your solution (.asax file?) and just use that to swap between XYZDatabase-TEST and XYZDatabase when you are fetching ConnectionStrings.
Add connection string to your Web.config like:
<connectionStrings>
<add name="XYZDatabase-TEST" connectionString="Server=.\SQLEXPRESS;Database=XYZDatabase-TEST";integrated security=SSPI;" providerName="System.Data.SqlClient" />
</connectionStrings>
Then open you Web.Release.config and add
<connectionStrings>
<add name="XYZDatabase-TEST"
connectionString="Data Source=OTHERSERVER;Initial Catalog=XYZDatabase-TEST;Persist Security Info=True;User ID=sa;Password=password" providerName="System.Data.SqlClient"
xdt:Transform="SetAttributes"
xdt:Locator="Match(name)"/>
</connectionStrings>
Now, everytime you will publish you application to deployment server using Release configuration it will use the connection string from web.release.config
Note that this transformation will not work locally when you debug. You must publish to run the web.config transformation.
I am using Entity Framework Code First 4.3 + Azure and having difficulties connecting to the database. The error I get is the following (on the first query):
Keyword not supported: 'server'.
I have the following connection set up in my Web.config
<configSections>
type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</configSections>
<connectionStrings>
<add name="TestDBContext"
connectionString="Server=tcp:[SUBSCR].database.windows.net,1433;Database=[MyDB];User ID=[user];Password=[pass];Trusted_Connection=False;Encrypt=True;PersistSecurityInfo=True"
providerName="System.Data.EntityClient" />
</connectionStrings>
My DbContext implementing class uses the connection string's name:
public class MyContext : DbContext, IMyContext
{
public MyContext()
: base("TestDBContext")
{
Configuration.LazyLoadingEnabled = true;
Configuration.ProxyCreationEnabled = true;
}
Can you tell what is going on?
I just had the same problem.
You're missing all the metadata in the connection string that Entity Framework requires. The connection string provided by SQL Azure needs to inserted within the provider connection string parameter of EF's connection string.
<add name="MyConnectionString" connectionString="metadata=res://*/Model.Model.csdl|res://*/Model.Model.ssdl|res://*/Model.Model.msl;provider=System.Data.SqlClient;provider connection string="[PUT SQL AZURE CONN STRING HERE]"" providerName="System.Data.EntityClient" />
You'll need to use the metadata from your own project. I pulled that metadata from an EF project generating from an existing database.
I had the same problem. I solved, putting in the web.config this connectionstring:
<add name="eManagerTurModelConnection" connectionString="metadata=res://*/ORM.eManagerFinanceModel.csdl|res://*/ORM.eManagerFinanceModel.ssdl|res://*/ORM.eManagerFinanceModel.msl;provider=System.Data.SqlClient;provider connection string="Data Source=<server>.database.windows.net;Initial Catalog=eManagerTur;Integrated Security=False;User ID=<user>;Password=<Password>;Connect Timeout=15;Encrypt=False;TrustServerCertificate=False;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
And after I removed the connectionstring of my website, worked, because it was not getting the connection string that I added in my web.config.
English bad... =)
The provider should be providerName="System.Data.SqlClient"
I connected to Azure from VS and then looked at the properties and set my connection string and provider name.
<add name="context" connectionString="Data Source=myServer,myPort;Initial Catalog=myDBName;Persist Security Info=True;User ID=myUserName;Password=myPassword;" providerName="System.Data.SqlClient"/>
I was then able to run update-database with no issues.
i tried like this, it may help you. may be 1433 is making problem, is it port no ? or what? . try like this.
check this link Windows Azure with Sql
<add name="dbContext" connectionString="Server=tcp:xxxxxxxx.database.windows.net;Database=xxxxxxxx;User ID=xxxxxxx#xxxxxxxxx;Password=xxxxxxxxxx;Trusted_Connection=False;Encrypt=True;" providerName="System.Data.EntityClient" />
Try this:
Data Source=tcp:YOUR-DATABASE-HERE.database.windows.net,1433;
Database=GolfRounds;
User ID=YOUR-USERNAME#YOUR-SERVER; Password=YOUR-PASSWORD; Trusted_Connection=False; Encrypt=True;
There is also an MSDN article at http://msdn.microsoft.com/en-us/library/windowsazure/ff951633.aspx that may be helpful.
I had a similar problem where I did not have access to the metadata, in this case you need to use System.Data.SqlClient as the provider. You will also need to add MultipleActiveResultSets=True to your connection string
For sample I'm using this connection string :
<connectionStrings>
<add name="PicturesDatabase"
connectionString=" Server=.;
Database=SomeprojectDatabase;
Trusted_Connection=True;"
providerName="System.Data.SqlClient"/>
<../>
And then I use it in Application_Start() :
Database.DefaultConnectionFactory =
new SqlConnectionFactory(ConfigurationManager.
ConnectionStrings["PicturesDatabase"].ConnectionString);
And in my database I get this really strange new Database :
MyAppNamespace.Models.PicturesCatalog
with two tables dbo.EdmMetadata and dbo.Pictures
Tables are fine, but why doesn't it create a new database named PicturesDatabase (as in connection string) with those tables ?
I've tried dropping this table few times, I did try creating PicturesDatabase and using it... but it still generates this MyAppNamespace.Models.PicturesCatalog. What is the problem with it ? And how do I fix it ?
System.Data.Entity.Infrastructure.SqlConnectionFactory is not meant to use in this way. This connection factory includes a constructor that allows us to override pieces of the final connection sting, such as username, password and server and not the whole thing.
For example, we can change the Database Server like this:
Database.DefaultConnectionFactory =
new SqlConnectionFactory("Server=MyDatabaseServer");
What you try to do here can be easily accomplished by providing a connection string in your app.config that matches the name of your DbContext - I assume it's PicturesCatalog:
<connectionStrings>
<add name="PicturesCatalog" connectionString="data source=.;
Initial Catalog=PicturesDatabase; Trusted_Connection=True;"
providerName="System.Data.SqlClient" />
</connectionStrings>
I am working in Visual Web Developer 2010 Express, and using the Entity Framework code-first CTP. I am able to do this with the new SQL Server CE but I am unable to find a connection string to work with SQL Server Express.
This one, using the SQL Server CE beta, works fine (database is created and recreated on model changes).
<add name="TrempimModel"
connectionString="data source=|DataDirectory|TrempimModel.sdf"
providerName="System.Data.SqlServerCe.4.0" />
This one, which I copied from the aspnetdb connections string,
<add name="TrempimModel"
connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;
AttachDBFilename=|DataDirectory|TrempimModel.mdf;User Instance=true"
providerName="System.Data.SqlClient" />
Gives the following message on startup:
Unable to complete operation. The supplied SqlConnection does not specify an initial catalog
So how to make it work with SQL Server Express?
The problem with your connection string here is:
<add name="TrempimModel"
connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;
AttachDBFilename=|DataDirectory|aspnetdb.sdf;
User Instance=true"
providerName="System.Data.SqlClient" />
You're basically defining what "server" you're connecting to - but you're not saying what database inside the file to connect to. Also - the file extension for SQL Server Express database files is .mdf (not .sdf - that's SQL Server Compact Edition) - you need to take that into account, too! (was a typo, according to comment by OP).
You need to define an extra database=.... (or Initial Catalog=.....) in your connection string:
<add name="TrempimModel"
connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;
database=YourDatabaseName;
AttachDBFilename=|DataDirectory|aspnetdb.mdf;
User Instance=true"
providerName="System.Data.SqlClient" />
Then it should work just fine.
For more background and tons of samples, check out the ConnectionStrings web site.