EntityConnection throws the exception when create the connection instance - entity-framework

In my EF project if I execute the following
using (EntityConnection con = new EntityConnection("name=HCMConnection"))
it throws the exception
The specified named connection is either not found in the configuration,
not intended to be used with the EntityClient provider, or not valid.
The connection string is in the Web.Config and it looks like following
<add name="HCMConnection" connectionString="Data Source=DEV-PROG-01;
Initial Catalog=HCM;
user id=HCMUser;
password=*******;
MultipleActiveResultSets=True"
providerName="System.Data.SqlClient" />
I suspect it does no like the SqlClient provider, does not it?
Thanks.

I believe you should have (replace settings class with the correct one for your app type). There is no EntityConnection constructor that can take the connection string name as a param to work.
using (EntityConnection con = new EntityConnection(SettingsClass.HCMConnection))
However its probably a better idea to let the dbcontext manage the connection instead of doing it manually, this constructor can take just the connection name.
using (MyDbContext con = new MyDbContext ("HCMConnection"))
And even better in your context class
public MyDbContext()
: base("HCMConnection")

Paul
Not clear what is the SettingsClass in my case, but I decided to use the same context to use its connection:
public ActionResult Education(ModelHCMContainer model)
{...
and execute the following
using (DbCommand cmd = model.Database.Connection.CreateCommand())
{
model.Database.Connection.Open();
try
{
cmd.CommandText = String.Concat("select ed.*,", ...
"order by ed.DateStart DESC");
using (var _reader = cmd.ExecuteReader())
{
using (ModelHCMContainer context = new ModelHCMContainer())
{
var records = ((IObjectContextAdapter)context).ObjectContext.Translate<HCMApplication.Models.POCO.Profile.HCMEducationPOCO>(_reader);
items = records.ToList();
}
}
}
finally
{
model.Database.Connection.Close();
}
}
It seems like working fine.
Thanks.

Related

How to set UserID and Password in EnterpriseLibrary 6.0

I have coded like the below:
#Code
DatabaseProviderFactory factory = new DatabaseProviderFactory();
database = factory.Create("DBinstanceName");
ConfigFile Entries
<oracleConnectionSettings>
<add name="CNQ" />
</oracleConnectionSettings>
<connectionStrings>
<add name="CNQ" connectionString=" Min Pool Size=0;Connection Lifetime=120;Max Pool Size=50; Data Source=(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST= XXXX.com)(PORT=1521))) (CONNECT_DATA = (SID = cnq) (SERVER = DEDICATED) ) );"
providerName="Oracle.DataAccess.Client" />
</connectionStrings>
With the above code and config settings, the DatabaseObject is created perfectly. When I verify the connectionstring it has the values what I had mentioned in the connnection string. So far good.
Now, I have to add the UserId & Password to the connection string at the runtime. There is no methods I could find to add the user credentials to the existing connection string. Becuase, in the Database object the connection string is READ ONLY.
The only way I find is to set in the configuration file[App.config], which is not the way we want, because for every user, we have a separate userid and password in the Oracle database.
In fact, I had tried by settings the connections at the command object, and passed the command object to the execute reader, even then also the enterprise library 6.0, not taking the connection we set in the command object.
Please help us how to set the userid and password in the runtime.
Thanks in advance
In order to set connection string values at runtime you will have to programmatically create your database objects. For example:
Database database = new GenericDatabase(GetConnectionString(),
DbProviderFactories.GetFactory("Oracle.DataAccess.Client"));
Or if you are using OracleDatabase something like:
OracleDatabase database = new OracleDatabase(GetConnectionString());
You could use extension methods to hide a bit of the ugliness:
DatabaseProviderFactory factory = new DatabaseProviderFactory();
Database db = factory.CreateWithConnectionString(GetConnectionString(),
DbProviderFactories.GetFactory("Oracle.DataAccess.Client"));
db = factory.CreateOracleDatabase(GetConnectionString());
public static class DatabaseProviderFactoryExtensions
{
public static Database CreateWithConnectionString(this DatabaseProviderFactory factory,
string connectionString,
DbProviderFactory dbProviderFactory)
{
return new GenericDatabase(connectionString, dbProviderFactory);
}
public static Database CreateOracleDatabase(this DatabaseProviderFactory factory,
string connectionString)
{
return new OracleDatabase(connectionString);
}
}
Another way to approach the issue if you know what connections you will have in advance (still at runtime but perhaps at application startup) is to use the DatabaseFactory.SetDatabases method to return the correct database based on a key. Unfortunately, the method only takes a single string so you can't specify nicely the username and password but you might be able to do something like this:
DatabaseFactory.SetDatabases(() => GetDatabase("Default"),
(dbName) => GetDatabase(dbName));
Database db = DatabaseFactory.CreateDatabase();
public Database GetDatabase(string dbName)
{
string connectionString = GetConnectionString(dbName);
return new OracleDatabase(connectionString);
}
Where the GetConnectionString method can create the proper connection string based on a name. However, I'm guessing this last way might not be the best given your description.
Thanks for your response.
Because I am using the Enterprise Library 6.0, only the First answer only works.
Database database = new GenericDatabase(GetConnectionString(),
DbProviderFactories.GetFactory("Oracle.DataAccess.Client"));
[or]
Oralce.DataAccess.Client.OralceClientFactory ocf = new Oracle.DataAccess.Client.OracleClientFactory();
Database database = new GenericDatabase(GetConnectionString(), ocf);
Thanks

Entity Framework MigrateDatabaseToLatestVersion giving error

I am attempting to use Entity Framework code based migrations with my web site. I currently have a solution with multiple projects in it. There is a Web API project which I want to initialize the database and another project called the DataLayer project. I have enabled migrations in the DataLayer project and created an initial migration that I am hoping will be used to create the database if it does not exist.
Here is the configuration I got when I enabled migrations
public sealed class Configuration : DbMigrationsConfiguration<Harris.ResidentPortal.DataLayer.ResidentPortalContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(Harris.ResidentPortal.DataLayer.ResidentPortalContext context)
{
// This method will be called after migrating to the latest version.
// You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
}
}
The only change I made to this after it was created was to change it from internal to public so the WebAPI could see it and use it in it's databaseinitializer. Below is the code in the code in the Application_Start that I am using to try to initialize the database
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ResidentPortalContext, Configuration>());
new ResidentPortalUnitOfWork().Context.Users.ToList();
If I run this whether or not a database exists I get the following error
Directory lookup for the file "C:\Users\Dave\Documents\Visual Studio 2012\Projects\ResidentPortal\Harris.ResidentPortal.WebApi\App_Data\Harris.ResidentPortal.DataLayer.ResidentPortalContext.mdf" failed with the operating system error 2(The system cannot find the file specified.).
CREATE DATABASE failed. Some file names listed could not be created. Check related errors.
It seems like it is looking in the totally wrong place for the database. It seems to have something to do with this particular way I am initializing the database because if I change the code to the following.
Database.SetInitializer(new DropCreateDatabaseAlways<ResidentPortalContext>());
new ResidentPortalUnitOfWork().Context.Users.ToList();
The database will get correctly created where it needs to go.
I am at a loss for what is causing it. Could it be that I need to add something else to the configuration class or does it have to do with the fact that all my migration information is in the DataLayer project but I am calling this from the WebAPI project?
I have figured out how to create a dynamic connection string for this process. You need to first add this line into your EntityFramework entry on Web or App.Config instead of the line that gets put there by default.
<defaultConnectionFactory type="<Namespace>.<ConnectionStringFacotry>, <Assembly>"/>
This tells the program you have your own factory that will return a DbConnection. Below is the code I used to make my own factory. Part of this is a hack to get by the fact that a bunch of programmers work on the same set of code but some of us use SQL Express while others use full blown SQL Server. But this will give you an example to go by for what you need.
public sealed class ResidentPortalConnectionStringFactory: IDbConnectionFactory
{
public DbConnection CreateConnection(string nameOrConnectionString)
{
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(ConfigurationManager.ConnectionStrings["PortalDatabase"].ConnectionString);
//save off the original catalog
string originalCatalog = builder.InitialCatalog;
//we're going to connect to the master db in case the database doesn't exist yet
builder.InitialCatalog = "master";
string masterConnectionString = builder.ToString();
//attempt to connect to the master db on the source specified in the config file
using (SqlConnection conn = new SqlConnection(masterConnectionString))
{
try
{
conn.Open();
}
catch
{
//if we can't connect, then append on \SQLEXPRESS to the data source
builder.DataSource = builder.DataSource + "\\SQLEXPRESS";
}
finally
{
conn.Close();
}
}
//set the connection string back to the original database instead of the master db
builder.InitialCatalog = originalCatalog;
DbConnection temp = SqlClientFactory.Instance.CreateConnection();
temp.ConnectionString = builder.ToString();
return temp;
}
}
Once I did that I coudl run this code in my Global.asax with no issues
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ResidentPortalContext, Configuration>());
using (ResidentPortalUnitOfWork temp = new ResidentPortalUnitOfWork())
{
temp.Context.Database.Initialize(true);
}

Using SimpleMembership with EF model-first

Can SimpleMembership be used with EF model-first? When I try it, I get "Unable to find the requested .NET Framework Data Provider" when I call WebSecurity.InitializeDatabaseConnection.
To put it another way: I can't get the call to WebSecurity.InitializeDatabaseConnection to work when the connection string employs the System.Data.EntityClient provider (as it does when using the model-first paradigm).
To repro the issue, create an MVC 4 app, and replace the code-first UserProfile entity class (which you get for free with the MVC 4 template) with a model-first User class that you have created in the Entity Designer:
Create an MVC 4 app in VS 2012 and add a new, blank Entity Data
Model.
Add a new Entity named User to the model, with fields for Id,
UserName, and FullName. So, at this point, the User data entity is
mapped to a Users table and is accessed via a funky connection
string that employs the System.Data.EntityClient provider.
Verify that the EF can access the User entity. One easy way to do
that is to scaffold out a Users controller based on the User table
and its associated DbContext.
Edit the AccountModels.cs file to remove the UserProfile class and
its associated UsersContext class. Replace the references to the
(now missing) UserProfile and UsersContext classes with references
to your new User class and its associated DbContext class.
Move the call to InitializeDatabaseConnection from the
InitializeSimpleMembershipAttribute filter class to the
Application_Start method in Global.asax.cs. While you're at it,
modify the arguments to use your new User entity's connection
string, table name, and UserId column name.
Delete the (no longer used) InitializeSimpleMembershipAttribute
class and the references to it.
When you run the repro, it will get an Exception at the call to InitializeDatabaseConnection.
Bob
SimpleMembership can work with model first. Here is the solution.
1.InitializeSimpleMembershipAttribute.cs from MVC 4 Internet Application templete should look like this
namespace WebAndAPILayer.Filters
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
{
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
try
{
WebSecurity.InitializeDatabaseConnection("ConnStringForWebSecurity", "UserProfile", "Id", "UserName", autoCreateTables: true);
}
catch (Exception ex)
{
throw new InvalidOperationException("Something is wrong", ex);
}
}
}
}
}
2.Delete CodeFirst Classes from AcountModel.cs
3.Fix AccountCotroler.cs to work with your Model-first DbContext (ExternalLoginConfirmation(RegisterExternalLoginModel model, string returnUrl) method)
4.Define your "ConnStringForWebSecurity" connection string which is not same as that funky conn string for model-first db access, notice that we use provider System.Data.SqlClient not System.Data.EntityClient
<connectionStrings>
<add name="ModelFirstEntityFramework" connectionString="metadata=res://*/Context.csdl|res://*/Context.ssdl|res://*/Context.msl;provider=System.Data.SqlClient;provider
connection string="data source=.\SQLEXPRESS;Initial
Catalog=aspnet-MVC4;Integrated
Security=SSPI;multipleactiveresultsets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
<add name="ConnStringForWebSecurity" connectionString="data source=.\SQLEXPRESS;Initial Catalog=aspnet-MVC4;Integrated
Security=SSPI" providerName="System.Data.SqlClient" />
</connectionStrings>
That's a bug in MVC 4. There's a workaround in this blog post.
As an action filter, InitializeSimpleMembershipAttribute hooks into OnActionExecuting to perform the lazy initialization work, but this can be too late in the life cycle. The Authorize attribute will need the providers to be ready earlier if it needs to perform role based access checks (during OnAuthorization). In other words, if the first request to a site hits a controller action like the following:
[Authorize(Roles="Sales")]
.. then you’ll have an exception as the filter checks the user’s role but the providers aren’t initialized.
My recommendation is to remove ISMA from the project, and initialize WebSecurity during the application start event.
1 - You need to enable migrations, prefereably with EntityFramework 5
2 - Move your
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "EmailAddress", autoCreateTables: true);
to your Seed method in your YourMvcApp/Migrations/Configuration.cs class
protected override void Seed(UsersContext context)
{
WebSecurity.InitializeDatabaseConnection(
"DefaultConnection",
"UserProfile",
"UserId",
"UserName", autoCreateTables: true);
if (!Roles.RoleExists("Administrator"))
Roles.CreateRole("Administrator");
if (!WebSecurity.UserExists("lelong37"))
WebSecurity.CreateUserAndAccount(
"lelong37",
"password",
new {Mobile = "+19725000000", IsSmsVerified = false});
if (!Roles.GetRolesForUser("lelong37").Contains("Administrator"))
Roles.AddUsersToRoles(new[] {"lelong37"}, new[] {"Administrator"});
}
Now EF5 will be in charge of creating your UserProfile table, after doing so you will call the WebSecurity.InitializeDatabaseConnection to only register SimpleMembershipProvider with the already created UserProfile table (In your case, you can replace the "UserProfile" parameter value with your custom table name), also tellling SimpleMembershipProvider which column is the UserId and UserName. I am also showing an example of how you can add Users, Roles and associating the two in your Seed method with custom UserProfile properties/fields e.g. a user's Mobile (number).
3 - Now when you run update-database from Package Manager Console, EF5 will provision your table with all your custom properties
For additional references please refer to this article with sourcecode:
http://blog.longle.net/2012/09/25/seeding-users-and-roles-with-mvc4-simplemembershipprovider-simpleroleprovider-ef5-codefirst-and-custom-user-properties/
this problem caused by WebSecurity.InitializeDatabaseConnection can't use connection string with System.Data.EntityClient provider name.
providing dual connection string isn't sound good, so you can generate the connection string for EF model first in the constructor in the partial class.
the code is look like bellow
public partial class MyDataContext
{
private static string GenerateConnectionString(string connectionString)
{
var cs = System.Configuration.ConfigurationManager
.ConnectionStrings[connectionString];
SqlConnectionStringBuilder sb =
new SqlConnectionStringBuilder(cs.ConnectionString);
EntityConnectionStringBuilder builder =
new EntityConnectionStringBuilder();
builder.Provider = cs.ProviderName;
builder.ProviderConnectionString = sb.ConnectionString;
builder.Metadata = "res://*/MyDataContext.csdl|" +
"res://*/MyDataContext.ssdl|res://*/MyDataContext.msl";
return builder.ToString();
}
public MyDataContext(string connectionName) :
base(GenerateConnectionString(connectionName)) { }
}
with this trick you can use single connection string on your web config, but one problem you can't use default constructor on your datacontext, instead you should seed connection string name everywhere when you instantiate the datacontext. but it is not a big problem when you use dependency injection pattern.
I´m not able to work with EF and WebMatrix webSecurity class so to avoid this problem and go ahead:
Change my Ef model first to code first.
Change the connection string to use providerName="System.Data.SqlClient"(removing all the metadata information) or use the EF connection
In my case the model, data and web are different proyects so for me is not an issue to remove this information from the web.config on the web.project.
Nowadays websecuroty.initializedatabase dosen't run with EF connection string.
I wish this helps

EF 5 Changing Connection String at Runtime

Ok, I want to recreate a project that I created using EF 4.1 to EF 5.0, simple enough or at least I thought. One of the things in my old project is that I was able to change the database connection string at runtime in EF 4.1:
using (var myContext = new MyEntities(ConnectionString))
{
}
Easy-peasy but in EF 5.0 you have to do this differently:
string connectionString = "data source=LocalHost;initial catalog=MyDatabase;user id=MyUserName;password=MyPassword;multipleactiveresultsets=True;App=EntityFramework";
using (var myContext = new MyEntities())
{
myContext.Database.Connection.ConnectionString = connectionString;
}
Now, this took me a better part of two hours to figure out, so I guess my question is this the proper way of changing the connection string at runtime or not? If it is why did they make this change?
I did find this Link but it didn't work. I received the error as detailed in the first comment of the first answer by Ladislav Mrnka. I later found this Link which seems to work fine.
UPDATE
I re-read the first link I posted and I found another solution, I simply created a partial class:
public partial class MyEntities : DbContext
{
public MyEntities(string connectionString) : base(connectionString)
{
Database.Connection.ConnectionString = connectionString;
}
}
Use the context constructor overload that takes the connection string as a parameter.
Create a class with the same name as the Target ContextClass class next to the main class
like this :
public CustomerContext( string connectionString)
: base(connectionString)
{
}
For using :
using (var context = new CustomerContext("connectionString"))
{
}
Or
var customerContext=new CustomerContext("yorConnectionString");
var customer=CustomerContext.customer.FirstOrDefault(x=>x.id==1).FirstName;
Have a look at other link Setup Entity Framework For Dynamic Connection String.
It says - " you can do it by creating another partial class as the Entities class is declared partial"

Single Connection String with Multiple Entity Framework Models?

At work we currently have a very large web application with a connection to a massive database. We have been using Entity Framework for a while now and to make things easier we divided the database into many Entity models. This works well for us but we ran into an issue. Each EF model needs its own connection string due to the metadata part of the connection string. Managing so many connection string is a pain.
Now I have a solution that I think will work. I am going to create a class that will have the metadata info saved as a property also concatenated to the standard connection string in the web.config. So when we use the connection string "Database.EntityConnectionString" it will give me the Entity Connection string but we only have to manage a single connection string in the web.config. We will still have to manage the class with the metadata but Models don't change very much and we don't create them often so maintenance should be fine. My question, is there a better way of dealing with this issue or how would you do it?
Thanks!
This is how I have implemented my solution to this problem:
namespace DBLibrary
{
public enum Models
{
Model1,
Model2
}
public static class Database
{
public static string EntitiesConnectionString(Models model)
{
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(ConfigurationManager.ConnectionStrings["Default"].ConnectionString);
builder["MultipleActiveResultSets"] = true;
builder["Connect Timeout"] = 30;
EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
entityBuilder.Provider = "System.Data.SqlClient";
entityBuilder.ProviderConnectionString = builder.ConnectionString;
switch (model)
{
case Models.Model1:
entityBuilder.Metadata = "res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl";
return entityBuilder.ToString();
case Models.Model2:
entityBuilder.Metadata = "res://*/Model2.csdl|res://*/Model2.ssdl|res://*/Model2.msl";
return entityBuilder.ToString();
default:
throw new Exception("Invalid model, no connection string defined");
}
}
}
}
I still need to clean up the code and all but I think this give you a good idea on how this can be implemented. I would still be very interested if there are different and better ways of doing this.
Thanks!
Add Default Construction in your Class
public class ItemContext : DbContext
{
public DbSet<Item>Items get; set; }
public DbSet<ItemDetail> ItemDetails { get; set; }
public ItemContext ()
{
this.Database.Connection.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
}
}
I had the same problem. I have solved it by following way:
I have created two edmx file, but while creating second edmx file, i ignored the connection string to be save in config file. This way my config file will hold only one Connection string.
Then i modified following lines in my connection string:
<add name="MyDbContext" connectionString="metadata=res://*/;provider=System.Data.SqlClient;provider connection string="data source=abc;initial catalog=mydb;persist security info=True;user id=myuser;password=password;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
Just replace "res://model1.csdl" with "res://*/" and it works like a charm.
You can specify this connection name in constructor of your dbcontext class like:
public MyDbContext() : base("name=NameOfYourConnectionString") // Name of your connection string
{ }
Note: I am using Entity Framework 5.0.