SimpleMembershipInitializer won't initialize - asp.net-mvc-4

I am struggling with getting a simplemembership scenario working in my EntityFramework / MVC4 / DatabaseFirst project. I've found plenty of examples for working with code first, but nothing for DB first.
The problem I'm encountering is the the InitializeDatabaseConnection is throwing an error ("Unable to find the requested .Net Framework Data Provider. It may not be installed.") The code looks like this :
WebSecurity.InitializeDatabaseConnection("DALEntities", "tblContacts1", "ContactID", "EMail", autoCreateTables: true);
I am not sure what DataProvider is failing. If I try to trace 'into' the InitializeDatabaseConnection call, it immediately throws the error.
What am I missing?
Info:
DALEntities is the name of the connectionString that the rest of EF uses. The following code works just fine....
public ActionResult Test() {
using (var db = new DALEntities()) {
var query = from i in db.TBLINVENTORies
orderby i.ITEMNAME
select i;
var cnt = query.Count();
string str = "Total Inventory: " + cnt;
return Content(str);
}
}
My connection strings section from the web.config:
<connectionStrings>
<add name="DALEntities" connectionString="metadata=res://*/DAL.DAL.csdl|res://*/DAL.DAL.ssdl|res://*/DAL.DAL.msl;provider=System.Data.SqlClient;provider connection string="data source=SOMECOMPUTER;initial catalog=SOMEDB;persist security info=True;user id=SOMEID;password=SOMEPASS;multipleactiveresultsets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
This post seems to be asking the same question (but in context of model-first), but there is no solution yet : Using SimpleMembership with EF model-first
Also, I see that there is an overload for WebSecurity.InitializeDatabaseConnection() with the help text: Initializes the membership system ((blah blah <snip> ProviderName: the name of the ADO.NET data provider. If you want to use Microsoft SQL Server, the WebMatrix.WebData.WebSecurity.InitializeDatabaseConnection(String, String, String, String, Boolean) overload is recommended . I do wish to connect to a MSSQL server...will this be required?

The provider giving you trouble is the one specified in your connection string which is System.Data.EntityClient. I suspect the problem is because your project is database-first whereas the simple membership is using code-first. I do not think you can mix these approaches in a single database. Try putting it back to where the DefaultConnection is used for IntializeDatabaseConnection. There should have been a DefaultConnection in your web.config generated by the MVC4 scaffolding. This connection string usually uses System.Data.SqlClient as the provider.
If you want to keep the simple membership in the database used to store domain information (i.e. DALEntities) then you will need to change your method for using EF on the domain to code-first. If you want to keep your project database-first you need to design your own membership schema in the database and develop custom member and role providers. This is probably the best approach if you are really trying to integrate user information into your domain model.

For simplicity and clarity keep two connection strings pointing to the same database. One for EF (doesn't matter if code first or data first) and one for your WebSecurity stuff. (As Chad and Erik said)
<add name="DataEntities" connectionString="metadata=res://*/Models.DataEntities.csdl|res://*/Models.DataEntities.ssdl|res://*/Models.DataEntities.msl;provider=System.Data.SqlClient;provider connection string='data source=[YOUR_SERVER];initial catalog=[YOUR_DATABASE];integrated security=True;MultipleActiveResultSets=True;App=[YOUR_APP_NAME]'" providerName="System.Data.EntityClient" />
<add name="DataDB" connectionString="data source=[YOUR_SERVER];initial catalog=[YOUR_DATABASE];integrated security=True;MultipleActiveResultSets=True;App=[YOUR_APP_NAME]" providerName="System.Data.SqlClient" />
Note that the providers are different: EF uses System.data.EntityClient and non-EF one uses System.Data.SqlClient.

Related

How to change the database in a WCF service connection string?

In Azure, I have a database called Sismos, this was targeted by my WCF service, I created a copy of this database like this on Azure:
CREATE DATABASE sismos_cfe AS COPY OF Sismos;
This was because the initial database was only a for testing and will be used for other purposes and this new one will handle all the work for this WCF servive.
In my WCF service, I changed the following line in my Web.config file:
<connectionStrings>
<add name="Model1Container" connectionString="metadata=res://*/Sismos.csdl|res://*/Sismos.ssdl|res://*/Sismos.msl;
provider=System.Data.SqlClient;provider connection string="data source=*******.database.windows.net;
initial catalog=Sismos;persist security info=True;user id=*******;password=*****;
multipleactiveresultsets=True;application name=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
With this:
<connectionStrings>
<add name="Model1Container" connectionString="metadata=res://*/Sismos.csdl|res://*/Sismos.ssdl|res://*/Sismos.msl;
provider=System.Data.SqlClient;provider connection string="data source=******.database.windows.net;
initial catalog=sismos_cfe;persist security info=True;user id=*****;password=******;
multipleactiveresultsets=True;application name=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
And this line in my app.cofig file:
<connectionStrings>
<add name="Model1Container" connectionString="metadata=res://*/Sismos.csdl|res://*/Sismos.ssdl|res://*/Sismos.msl;
provider=System.Data.SqlClient;provider connection string="data source=******.database.windows.net;
initial catalog=Sismos;persist security info=True;user id=****;password=*****;
multipleactiveresultsets=True;application name=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
With this:
<connectionStrings>
<add name="Model1Container" connectionString="metadata=res://*/Sismos.csdl|res://*/Sismos.ssdl|res://*/Sismos.msl;provider=System.Data.SqlClient;
provider connection string="data source=******.database.windows.net;
initial catalog=sismos_cfe;persist security info=True;user id=****;password=*****;
multipleactiveresultsets=True;application name=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
As you can see, I only replaced the value of the initial catalog property, instead of pointing to Sismos, it now should point to cfe_sismos.
The problem I'm having is that when I try to access one of my endpoints that deals with deleting an entry in the database, no change is made in the database at all. With operations of selecting entries or editing/inserting an entry there's no problem. With the initial catalog property value eing Sismos there's no problem with any of the endpoints, in theory any database access should be directed to the cfe_sismos database.
Was it not enough with me replacing the initial catalog property value? Any help will be appreciated.
EDIT
I just noticed that there's also problems and odd behaviour when editing an entry, for example, if I have an entry in my table Users and I edit the Last_Name, the change won't be reflected when I check my database on Azure, but if I call the endpoint that returns the users, the change will be present, I gave some time to see if there was some kind of delay preventing from showing the newest values in Azure, but it didn't show any changes. How can I be making changes in the database without those changes being shown in the actual database? If I try to insert a new entry into a table, the entry will be shown with no problem.
So in summary, through my endpoints in my WCF service, if I insert something it will be shown in azure, if I edit something it won't be shown in Azure(but the change will be available when calling the respective endpoint) and if I want to delete something it won't be shown in Azure nor the change will be reflected when calling the endpoint.
If the database in Azure is not receiving any changes, then where am I getting all of the information? It's like a cached database exists somewhere, I'm really confused at the reason for this is happening.
I'm really confused at this odd behaviour, so I hope someone can help me. Thanks in advance.
I finally found the reason for the odd behaviour. The thing is that Entity Framework can't work with objects that are copied from another obtained from the Context object generated by Entity Framework.
What I was doing was storing the data from my entities into static Lists to avoid as many connections to the database as possible, only making connections when an insert, update or delete operations were needed. But when I tried to get an object from those lists and use it to update or delete on the database, since it wasn't obtained from the context, then the operations is invalid. This is why only insert operations were working properly, since those are new objects and can interact with no problem with the context.
So in the end I changed the logic for the update and delete operations on my DAO classes, so instead of doing this:
Clusters cluster = (from c in DatabaseInfoHolder.ListaClusters
where c.ClusterId == model.ClusterId select c).FirstOrDefault();
I went with this:
Clusters cluster = (from c in context.Clusters
where c.ClusterId == model.ClusterId select c).FirstOrDefault();
I was hoping for Entity Framework to recognize the values from the object in my static Lists, but it seems it doesn't work that way.
Your config says "initial catalog=sismos_cfe" but you said "CREATE DATABASE cfe_sismos"
sismos_cfe != cfe_sismos

How to specify a database when using InitializeDatabaseConnection()

I am working with the default Internet template when using MVC 4.0. How can I specify where the initial database is created? I have installed SQL Server Express 2012 and want the database created there instead of in the Visual Studio built-in SQL Server.
I did try using the default and then copying the database from VS to SQL Express 2012 but I don't seem to be able to back up the VS database.
Anyone have any idea?
Thanks, Mark
You need to add a connection string in the config which has a name matching the name of your context class, for example:
<connectionStrings>
<add name="FooBarContext" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=FooBar;Integrated Security=SSPI;MultipleActiveResultSets=true;" providerName="System.Data.SqlClient" />
</connectionStrings>
In the above, my context class is named FooBarContext which matches the connection string name. The context class looks something like this:
public class FooBarContext : DbContext
{
// etc.
}
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "Users", "Id", "Login", autoCreateTables: true);
where DefaultConnection — connection name in your web.config (in <connectionStrings>)

Invalid value for key attachdbfilename after renaming connectionString

I am building the sample MvcMovie tutorial for ASP.NET MVC 4. I'm using EntityFramework Code First features and created a connectionString as follows.
<add name="MoveDBContext"
connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDictionary|\Movies2.mdf;Integrated Security=True"
providerName="System.Data.SqlClient"
/>
Everything worked fine at this point. But then I realized that I named my connection string MoveDBContext instead of MovieDBContext and, being the perfectionist I renamed it. After doing this I now receive an error in my MoviesController/Index method.
public class MoviesController : Controller
{
private MovieDBContext db = new MovieDBContext();
public ActionResult Index()
{
return View(db.Movies.ToList()); // Error: Invalid value for key 'attachdbfilename'
}
...
}
If I change the name back to MoveDBContext the error goes away.
Can anyone tell me where this original name is being referenced?
EF, by default, looks for a connection string with the same name as the type that extends DbContext.
Or, better put by Scott:
By default, when you create a DbContext class with EF code-first, it
will look for a connection-string that matches the name of the
context-class. Since we named our context class “NerdDinners”, it
will by default look for and use the above “NerdDinners” database
connection-string when it is instantiated within our ASP.NET
application.
Edit:
After looking closer, I think your connection string is the problem. You've got DataDictionary instead of DataDirectory. Try this (line feeds added for readability):
<add name="MovieDBContext"
connectionString="Data Source=(LocalDB)\v11.0;
AttachDbFilename=|DataDirectory|\Movies.mdf;
Integrated Security=True"
providerName="System.Data.SqlClient" />
Apparently, as Ken said, the MoveDBContext was not being referenced.
I removed the entire connectionString from the web.config and everything still functioned correctly.
So, it still begs the question, "How did Visual Studio know to create a database in my SQLExpress instance?" and "Where is that configured at?"

Code-first Entity Framework not picking up web.config connection string when initializing

I have been using code-first entity framework. I have defined a connection in the web.config, with name matching the class name of my DbContext (in this example 'MyDbContext').
EF uses this connection with no problems when the database exists.
However, if I delete the database (to force EF to re-create it) EF creates the database on the local Sql Express server instead.
If I specify the full connection string in the DbContext class constructor like
public class ReykerSCPContext : DbContext
{
public ReykerSCPContext() :
base("Server=tcp:MyDBSErver.database.windows.net,1433;Database=MyDB;User ID=#######;Password=#######;Trusted_Connection=False;Encrypt=True;MultipleActiveResultSets=True;PersistSecurityInfo=True;") { }
}
then the database is created correctly on the server of choice. Great!
Can anyone tell me if this is correct behaviour as I am bashing my brains out. I would like it all to work from the web.config, so I don't need to necessarily rebuild and remember to change settings in code etc..
This should do it:
public class EFDbContext : DbContext {
public EFDbContext() : base("EFDbContext") {
}
public DbSet<Product> Products { get; set; }
}
You should have the connection string by the name of your context class in the web.config and that will do it. The web.config should be in root.
<connectionStrings>
<add name="EFDbContext" connectionString="Data Source = .; Initial Catalog = ITSDB; Integrated Security = true" providerName="System.Data.SqlClient"/>
</connectionStrings>
If you do
update-database -v
and it shows it is using IIS express instance instead of the value from the Web.Config , it means EF is confused when the local IIS express instance is running.
I had the same issue and was resolved by stop/delete IIS express.
"sqllocaldb.exe stop v11.0"
"sqllocaldb.exe delete v11.0”
Hop that helps someone!

Is it possible to create a common database class in VB.NET?

We have 3 databases providers we use to connect to our databases: DB2, MS SQL, and Interbase. I would like to create a single generic database wrapper class that can be used to talk to all three just by passing in the correct connection string, username, password, and the provider desired.
I don't want to have to add references and import all three providers in the database class. Is this possible?
I have done this before in Java using the Class.forName() function.
There is an abstract factory built into .NET 2.0 or later, an example of its use would be:
Dim factory As System.Data.Common.DbProviderFactory
factory = System.Data.Common.DbProviderFactories.GetFactory("System.Data.SqlClient")
Dim conn As System.Data.Common.DbConnection = factory.CreateConnection()
conn.ConnectionString = "connectionString"
conn.Open()
There are methods on DbProviderFactory like CreateCommand, CreateDataAdapter, etc.
If you do not want to have references to the individual providers in your application, you will need to handle this a little differently.
There are two main options I see - the first (and easiest) would be to use a dependency injection framework to just plugin the appropriate provider at runtime. This is simple, clean, and works well.
You could do it yourself without that, though. Just make a general purpose base class that provides the interface, and, for each provider, make a separate assembly (so the references are separated) that implements this base class. You can then use Activator.CreateInstance to create an instance of the appropriate type at runtime.
To expand on Patrick McDonald's answer, you can store the provider name and connection string in the <connectionStrings> section of your application configuration file. Then you don't need to have the providers hardcoded in the application:
ConnectionStringSettings c = ConfigurationManager.ConnectionStrings["MyConnectionName"];
if (c != null)
{
DbProviderFactory factory = DbProviderFactories.GetFactory(c.ProviderName);
IDbConnection connection = factory.CreateConnection();
connection.ConnectionString = c.ConnectionString;
...
}
Where your application configuration file contains a connectionStrings section something like:
<connectionStrings>
<add name="MyConnectionName" providerName="System.Data.SqlClient" connectionString="Data Source=serverName;Initial Catalog=DBName;Integrated Security=True"/>
</connectionStrings>
can you use framework 3.5 sp1?
if yes, you should look at Linq to Entity