I've created a new ASP.NET MVC 4 application, and would like it to use code first. However it doesn't seem to initially create the database file if it doesn't exist already. If I delete the .mdf file from the App_Data folder, then I get the following exception when the app tries to access the database:
System.Data.SqlClient.SqlException: Cannot attach the file '<path-to-db-file>.mdf' as database '<my-db-file-name>'.
If I run it in the app in the debugger, then I can see that the exception is occurring in the InitializeSimpleMembershipAttribute::OnActionExecuting method when calling LazyInitializer.EnsureInitialized. The caught exception is:
[System.Reflection.TargetInvocationException] {"Exception has been thrown by the target of an invocation."} System.Reflection.TargetInvocationException
With an inner exception of:
[System.InvalidOperationException] {"The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588"} System.InvalidOperationException
Which then has the first exception I mentioned above as the inner exception of that.
Any ideas what I'm doing wrong?
Update
I've just tried it with a brand new MVC4 app. I can replicate it by doing the following:
Create the MVC app in the VS wizard.
Run the app for the first time and go to the login page (note the mdf file now gets generated).
Delete the mdf file, and go back to the login page. The exception is now thrown.
Got into the same problem and found my solution here.
all you have to do is stop LocalDb by opening the VS developer command prompt and enter (without quotes):
"sqllocaldb.exe stop v11.0"
"sqllocaldb.exe delete v11.0"
Next time EF will regenerate the file as well as the db.
If you dig into your application's InitializeSimpleMembershipAttribute class you'll see the following overridden method of the ActionFilterAttribute class from which it inherits:
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);
}
Notice that comment. The application is checking once per run to ensure that Simple Membership has been properly initialized. Look at the private variables at the top of the class:
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
They are all static and they are all passed as refs. The important one here for your situation is _isInitialized. What LazyInitializer.EnsureInitialized does is checks the _isInitialized flag and if it is false it initializes the ref target it's passed, in this case the _initializer of type SimpleMembershipInitializer. At that point it sets the flag to true and moves on. If LazyInitializer.EnsureInitialized sees that the flag is true it does nothing but return the target. Since that flag is a static variable, it persists its value for the life of the application which means that after that first initialization EnsureInitialized will always simply return the target even if the database file no longer exists. In other words, if you delete the .mdf file after initialization the application will not know and exceptions will be thrown when the app tries to read or write from the database. In order to resolve this you have to restart the application, which means killing the dev server if that's what you're using or restarting the application in IIS.
So that is the problem that you are facing, but I suspect that many of the folks running across this question are having a similar but different issue where they receive an error message similar to this one when attempting to log in:
CREATE FILE encountered operating system error 5(Access is denied.) while attempting to open or create the physical file 'C:\path\to\your\project\App_Data\dbfile.mdf'.
CREATE DATABASE failed. Some file names listed could not be created. Check related errors.
This is very easy to solve to I'll cover that quickly here as well.
By default Visual Studio 2012 uses a pared down version of SQL Server Express called LocalDB. LocalDB will spin up a a child process of the application, and if you're running your application on Visual Studio's development server (eg http://localhost:[port] is what shows up in your browser) then you are running both the application and LocalDB under your user account, not under SYSTEM or NETWORKSERVICE. All you have to do to fix this is assign Modify permissions to your user for the App_Data folder of your project. Try the login again and the .mdf file should be created successfully.
If you're curious, you can learn more about LocalDB here.
You can handle Code First database initialization in the Application_Start method of Global.asax file in root folder of your project, like the following:
protected void Application_Start()
{
Database.SetInitializer<MyDBContext>(null);
}
If you pass null to SetInitializer it won't create or alter your database tables, you should do it manually.
The reason why the database is not re-generated is that Application_Start is fired only once during the application lifetime.
The MVC-generated code works with a database connection string named "DefaultConnection".
If you used a different name in Web.config, you need to refer to this name in:
InitializeSimpleMembershipAttribute.SimpleMembershipInitializer.ctor() in InitializeSimpleMembershipAttribute.cs).
UsersContext.ctor() in AccountModel.cs
(or just search for "DefaultConnection" in your project).
You should never delete autocreated .mdf files in Explorer, only through the SQL Management tools or in the Object Explorer.
The issue you are getting (and can replicate in the steps you've provided) is that the database is still registered in LocalDb.
You have to stop your IISExpress instance and restart it again (by pressing F5 in your Visual Studio). Then you will be able to create the database again.
what fixed it for me when I was receiving this error is that I changed the connection string in App.config file of my VS Project.
I have added this in the connection string:
<connectionStrings>
<add name="Blog" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;Integrated Security=true;AttachDbFileName=C:\Users\kostadin\Database1.mdf" providerName="System.Data.SqlClient" />
Hope this helps someone else.
Related
I have a simple data entry Windows Form with a datagridview display that links to a local database. When I run the program and try to add data on another computer, I get this message:
Unhandled exception has occurred in your application. If you click Continue, the application will ignore this error and attempt to continue. If you click Quit, the application will close immediately.
An attempt to attach an auto-named database for file C:\Users\roberto.yepez\Documents\Visual Studio\2010\Projects\Financial Aid Calculator\Financial Aid Calculator\StudentInfo1.mdf failed. A database with the same name exists, or specified file cannot be opened, or it is located on UNC share."
The file path is to the path on the computer where I coded the program.
Here is my code:
SqlConnection conn = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename='C:\Users\roberto.yepez\Documents\Visual Studio 2010\Projects\Financial Aid Calculator\Financial Aid Calculator\StudentInfo1.mdf';Integrated Security=True".ToString());
I am a self-taught coder, please help! :)
I believe you're running into a problem because your local sql server to which your code is trying to attach the StudentInfo1.mdf (whose path is in the connection string) already contains a database called StudentInfo1 - it decided to try and create a database of this name based on the name of the mdf file. I'm guessing that you can pick your own name by specifying Initial Catalog in your connection string but this would mean there are two databases with possibly the same set of tables and a potential for confusion
Per the comment I posted I would instead advocate that you use SQL Server Management Studio to permanently attach your db (you make have already done this) and then adjust your connection string so that it refers to the permanently attached db. This reduces the chances that your next question will be "my code says it's updating my db but I cannot see any changes!?"
Please move this connection string
"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename='C:\Users\roberto.yepez\Documents\Visual Studio 2010\Projects\Financial Aid Calculator\Financial Aid Calculator\StudentInfo1.mdf';Integrated Security=True"
to app.config file. When you deploy to production, change the paths in that app.config, according to the production machine settings.
You can even apply transformations on the app.config to deploy in various machines/scenarios.
I have developed c# WPF application, I am using MDF file for database,
my connection string looks like :
Data
Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\appDataBase.mdf;Integrated
Security=True;Connect Timeout=30
here I am replacing |DataDirectory| with user's appdata folder.
the database file is in user's appdata folder, I created a setup which
copies .mdf file to _users appdata folder when I install it in
client's computer, it works perfectly
but when I uninstalls and
reinstall it, I am not able to connect that file, getting the error:
Can't open database
"C:/users/myusername/appdata/roaming/myapplication/database/appDataBase.mdf"
requested by login, login failed, login failed for user..
File is there, but somehow it is used by SQL server and can't
open it. also while starting application every time I am creating
backup of that file, that one also failing with error
System.IO.IOException: The process cannot access the file
'C:\Users\myusername\AppData\Roaming\myapplication\Database\appDataBase.mdf'
because it is being used by another process.
Can anybody give me exact solution, because i have to use localdb only on my client computer , i don't want them let to do any extra configuration for installation of my app, i.am still facing iasue after i changed my code to close db connection on main window closing event.
This type of things happens because one of your object which is using that database is still running in the background so please dispose all the database related instance also dispose and close all the database related object in catch().
Try catch will help you to detect exact line number where you are getting error and also show due to which object you are getting error.
If you want to check why this is happening then open task manager and look out for services there you definitely find service which is holding object for database.
My development environment is C#, SQL Server 2014 LocalDB, SQL Server 2012 Express, Windows 10, Visual Studio 2015.
When users of my application need to move their localDB (.mdf) file to another place, another computer (LocalDB server), detaching from computer A and attaching to computer B and then, we can run BACKUP database command successfully.
However, in case users mistakenly detached or users changed their mind to use continuously in computer A, my application has to be able to re-attach the detached LocalDB database file (.mdf) to the same computer (same LocalDB server).
When I run BACKUP DATABASE command after my application re-attached the database file to same computer successfully, error message shows as,
Unable to open physical file, The process cannot access the dbfile because the dbfile is in use by another process
BACKUP DATABASE terminated abnormally
So, I entered Microsoft Server Management Studio and can see 2 dbfile with specific name as first is greendb.mdf (only name), second is c:\users\kay\appdata\greendb.mdf (with full path).
I think the c:\users\kay\appdata\greendb.mdf (with full path) is created when the database is detached. And when I click it through security-login-kay-user mapping, unlike other databases show their permissions inside, the detached database with full path doesn't show their permissions and show error message like,
Unable to cast 'System.DBNull' object to 'System.String' (Microsoft.SqlServer.Smo)
It seems Microsoft LocalDB Server still recognizes the detached database with full path and is confused with newly attached database (only name without full path).
Any excellent ideas will be highly appreciated !
Thank you so much !
In detaching localDB,
we have to run ALTER DATABASE ROLLBACK IMMEDIATE command first to terminate all the incomplete transactions.
Just to explain easily, Before we close a Restaurant, we have to announce to the customers in the Restaurant, 'This Restaurant will be closed very soon, please complete your eating and get outside before closing of Restaurant'
If you're needed to re-attach the localDB to same computer(same localDB Server),
Some activities like these have to be avoided to prevent the ghost(bug?).
1) Trial to open the localDB in code programmatically
2) It seems counting with the name of detached localDB also reminds the existence of localDB to the localDB Server.(SELECT COUNT dbname command in master database)
Strange thing which has to be fixed as a bug is,
if we detach a localDB from master DB, I think it has to be not able to open the detached localDB in code programmatically. However, code like SqlConnection.Open(); runs and pass by without any exception(error) and immediately the fullpath ghost is created.
It seems the name of detached localDB is deleted on master DB but the Server connects the detached localDB through the physical path in the provided connectionstring.
And to decide some localDB is needed to attached or to check it's detached or not, I've developed my own solution(simple code) to do this.
Hope my experience helps someone else.
Well, I worked a lot using attach and detach operation and finally I figured out that the best practice for us as a developers is working with scripts.
So, if you want to (detach) your db to re (attach) again either with a new name or the same name. I suggest you to generate scripts for your database and script it again.
if you run the script directly you will get an error because you have to delete the old data (the old / new have the same name) and script by default is using the db name which is written in the first line, sure you can remove this line and use the new database you want to use.
for scripting database including data, make sure to set preference from the wizard (Advanced settings => schema only / data only / schema and data.) choose schema and data
By default the choice is schema only.
choose a destination for your sql file, after running the script and deleting the old data. your backing up process should go with no problems.
I have a Windows Azure Mobile Services app that has a Code First generated database. The connection string (for when run locally) looks like this:
<add name="MS_TableConnectionString" connectionString="Data Source=(localdb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\<database_name.mdf;Initial Catalog=<database_name>;Integrated Security=True;MultipleActiveResultSets=True"
providerName="System.Data.SqlClient" />
I created a new Console App project, referencing the Mobile Services project, and copied this connection string to the App.config file
In Program.Main() I created a new instance of the Context class from the Designer in the Mobile Services project. But when I run the Console App, and try to access one of the DbSets made public by the Context, I get the following exception:
"An exception occurred while initializing the database. See the InnerException for details."
With an inner exception of:
"The underlying provider failed on Open."
Which in turn has an inner exception of:
"Cannot attach the file 'C:\\...\\<database_name>.mdf' as database '<database_name>'."
If I remove the AttachDbFilename part of the connection string in the Console App, I get the following exception at the same point in the code:
"Cannot create more than one clustered index on table 'dbo.<Table_Name>'. Drop the existing clustered index 'PK_dbo.<Table_Name>' before creating another"
Does anyone have any idea why it would be trying to create this new clustered index when there already appears to be one?
Or any ideas what connection string I should use just to get a normal read/write connection to the database without it doing anything weird? Is this related to database initialization?
Edit: I've had a bit more of a play around with this, this morning. I can get it working without exceptions if I remove the inheritance of "Microsoft.WindowsAzure.Mobile.Service.EntityData" from my model classes, so this appears to be pretty significant.
Ok I've just battled through this and got it working. Gonna type this up in case it helps anyone one day.
So the problem is something to do with the fact that my Code First model classes were inheriting from EntityData. As I said in my edit above, removing this inheritance does appear to fix the problem. I think this is because the EntityData class has both a property with a [Key] attribute and a separate property with a [Index(IsClustered = true)] attribute. Because you can't have more than one Clustered Index in a table, the database initialization fails. In the default Azure Mobile Services project, there must be some magic that means this doesn't happen somewhere - but from a separate project you get the "Cannot create more than one clustered index on table" exception.
So what I did was disable Database Initialization in the separate Console App by adding the line:
Database.SetInitializer<MobileServiceContext>(null);
...before the DbContext is instantiated.
This allows me to use the database initialized by the Mobile Services App as an existing database, without attempting to make any changes to it.
I also needed the following AppSetting in the config file of the Console App, in order for it to use the correct Schema Name:
<add key="MS_MobileServiceName" value="<CorrectSchemaName>" />
I'm trying to create a windows service and I need it to be able to write to the event logs. I've added an EventLog component to my Service project, and set the Log property to be ccs_wscln_log and the Source property to be ccs_wscln (same name as the service).
I have also created and installer for this project. My problem is that whenever I install the service, it creates the ccs_wscln registry key under
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application
when it SHOULD be
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\ccs_wscln_log.
The problem with this is that when I try to launch the service, I get an error that says
"The source 'ccs_wscln' is not registered in log 'ccs_wscln_log'. (It is registered in log 'Application'). The source and Log properties must be matched, or you may set Log to the empty string, and it will automatically be matched to the source property'.
I've found that if I delete the ccs_wscln registry key under the Application folder, when I start the service it will run and generate the ccs_wscln_log entry under EventLog. So my question is, when I install the application, why is it creating an entry for me automatically under Application, and how do I prevent it from doing this?
I found another post on SO that said I need to restart my computer if I had installed it before under Application, so I tried that but when I reloaded the solution, I couldn't even bring up the designer because it was complaining that the registry entry was missing and it would still install under Application anyways.
I created a tutorial for creating a Windows service from scratch using C#. I address the issue of writing to an application-specific log. See Step 9 here for details.
I think, you would need following in your ServiceInstaller class.
this.Installers.Clear();
Above code needs to be just before you are adding a range of installers.
That is because, EventLogInstaller is added by default. Calling clear will remove it.
Alternatively, you can loop through the installers collection, select the specific type (EventLogInstaller) and assign it required LogName and EventSource name.