Using Azure Mobile Services Code First Generated Context class in another project - c#

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>" />

Related

encrypt database connect string for azure website

seems there is no good way to encrypt database connect string for azure website (not cloud service), i already view the solution here
but, i can't store the database first entity framework connect string in the azure website setting, which will get below error, anyone knows how to make data base connect string secure in azure website using database first entity framework?
System.Data.Entity.Infrastructure.UnintentionalCodeFirstException: The context is being used in Code First mode with code that was generated from an EDMX file for either Database First or Model First development. This will not work correctly. To fix this problem do not remove the line of code that throws this exception. If you wish to use Database First or Model First, then make sure that the Entity Framework connection string is included in the app.config or web.config of the start-up project. If you are creating your own DbConnection, then make sure that it is an EntityConnection and not some other type of DbConnection, and that you pass it to one of the base DbContext constructors that take a DbConnection. To learn more about Code First, Database First, and Model First see the Entity Framework documentation here: http://go.microsoft.com/fwlink/?LinkId=394715
You don't have to include the connection string in the web.config for your site. You can manage the connection string in your azure account at:
App Services>[your_app_name]>Settings>Application settings
Under Connection strings section, you can set the key/value pair which is the connection name and the db connection string.
After you set those values, in the screen, the connection string will be hidden for display.

Using a project from Source control in a different computer

I have an ASP.NET MVC project that was completed on one system and saved to GitHub. Now I have downloaded the projected as a ZIP file from Github and I am trying to execute it. As there is no local database on my system, how should I create the database again without starting up with a new project and copying the code?
I do not want to create the SQL table manually when it can be scaffolded using MVC. AFAIK, when there is no existing database with the name of the database, the database is created and the tables are created. But no table or database is created.
It throws the following exception
An underlying operation failed an Open
Update
I could remove the above exception to get a new exception
The context cannot be used while the model is being created. This
exception may be thrown if the context is used inside the
OnModelCreating method or if the same context instance is accessed by
multiple threads concurrently. Note that instance members of DbContext
and related classes are not guaranteed to be thread safe.
More info on the Project
The project is using Windows Authentication. And the calls to every page in the project is validated before the page is viewed. As I have no table called Users in the database, I get an exception The underlying operation failed an Open. I tried to call the Create User method, and create a user with my current credentials, but I am unable to save changes to the database.
First in web.config find connection string and change Data Source
value to your SqlServer address, we assume you use SSMS in your
windows,
some thing like this:
<connectionStrings>
<add name="ApplicationConnectionString" connectionString="Data Source=.;Initial Catalog=DB;Persist Security Info=True;" providerName="System.Data.SqlClient" />
</connectionStrings>
Socond open package manager console from View and then write
Add-Migration InitialCreate
after executing this command, write
update-database

How do I modify Entity Framework 6 using Npgsql 3 to use an SSL connected string?

So far what I've tried is to verify that my certificates for SSL are correct and through command line (Using psql) and through a console application (Npgsql) I'm able to reach the database with SSL enabled (No password needed). This is working.. My problem starts with the SSL.
The application I'm working on has working Data Access to Postgre using Entity Framework 6 on non-SSL. However when I try to update the string to use SSL, I need to find a place to pass in the client-certificates. I've looked at different places. Right now, I have changed the DbContext() constructor to use base(DbConnection,bool) so that I can pass in a connection that has been provided the callback method. However, I get this error:
The context cannot be used while the model is being created. This
exception may be thrown if the context is used inside the
OnModelCreating method or if the same context instance is accessed by
multiple threads concurrently. Note that instance members of DbContext
and related classes are not guaranteed to be thread safe.
I've tried to apply different fixes from SO to solve this error, but to no avail.
Anything helps!

Entity Framework 5 : changing the database connection

I have a made an EntityFramework model based on my Demo Database.
I want to include connection strings for Staging and production and then in my Console App prompt the user to see which database they want to perform the operation on.
When I was prompted to setup the EF.edmx file I just chose to store the connection string in the app.config file. I have seen a link to change the Connection string of EntityFramework Context when initializing it here
However when I store another connection to my Staging Database, I get an error "Keyword not supported: 'metadata'"
So I stripped down the connection string not to include the EntityFramework type of parameters such as metadata=res://*/MyDBItems.csdl|res://*/MyDBItems.ssdl blah blah
and used a very simple database connection string
data source=myDB;initial catalog=myDB;user id=myUser;password=myPass;MultipleActiveResultSets=True;
now my Context does instanciate but when I get to a query I get another error about:
Code generated using the T4 templates for Database First and Model First development may not work correctly if used in Code First mode. To continue using Database First or Model First ensure that the Entity Framework connection string is specified in the config file of executing application. To use these classes, that were generated from Database First or Model First, with Code First add any additional configuration using attributes or the DbModelBuilder API and then remove the code that throws this exception.
How can I switch between different databases with Entity Framework 5, thanks!
forget it I got it....what I did...I made a 2nd constructor in the Context.cs file
public MyContext(string dbModel) : base("name="+dbModel) {
}
then in my app.config I have the various settings for the Demo,Staging & Production database connections....this took the full entityframework connection string. I think the link I provided was for Code-First but I am using Database First.

Exception when code first tried to create database

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.

Categories