How to configure Entity Framework to use different connection string when executing migrations and when working with the database.
The reason for that is quite simple, I do not want to have sa login for the website, but I want to be able to execute migrations.
After not finding anything on the web for how to do that, the Object Explorer helped.
The EF Migration Configuration class (where AutomaticMigrationsEnabled = true is set)
has also a property named TargetDatabase.
This can be set to whatever connection string you want like so:
TargetDatabase = new System.Data.Entity.Infrastructure.DbConnectionInfo(
ConfigurationManager.ConnectionStrings["ConnString"].ConnectionString,
ConfigurationManager.ConnectionStrings["ConnString"].ProviderName);
Related
I am trying to use Code First with Migrations. Even though there are no current changes to my model, I'm getting an exception. When I add a migration, the up and down are empty, but I get a runtime error with the message as follows:
An exception of type 'System.InvalidOperationException' occurred in
EntityFramework.dll but was not handled in user code
Additional information: The model backing the 'MyDataContext' context
has changed since the database was created. Consider using Code First
Migrations to update the database (http://go.microsoft.com/fwlink/?
My architecture is as follows:
DataAccess project that includes the context, fluid configurations and migrations code
Model project that contains the poco classes
Web API and MVC projects that each contain the connections string in their respective web.config files.
Additionally I have the following code:
DbInitializer
public static MyDataContext Create()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyDataAccess.MyDataContext, MyDataAccess.Migrations.Configuration>());
return new MyDataContext(ConfigurationManager.ConnectionStrings["MyDataContext"].ConnectionString, null);
}
I started with AutomaticMigrationsEnabled = false; in the migration Configuration constructor, as it was my understanding that this would allow (and require) me to have more control over when migrations were applied. I have also tried setting this to true but with the same result.
I added a new migration upon receiving this error, and the Up method was empty. I updated the database to this new migration, and a record was created in the _migrationHistory table, but I still receive the error when I attempt to run the application. Also, the seed data was not added to the database.
protected override void Seed(MyDataAccess.MyDataContext context)
{
IdentityResult ir;
var appDbContext = new ApplicationDbContext();
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(appDbContext));
ir = roleManager.Create(new IdentityRole("Admin"));
ir = roleManager.Create(new IdentityRole("Active"));
ir = roleManager.Create(new IdentityRole("InActive"));
var userNamager = new UserManager<User>(new UserStore<User>(appDbContext));
// assign default admin
var admin = new User { UserName = "administrator", Email = "myAdmin#gmail.com" };
ir = userNamager.Create(admin, "myp#55word");
ir = userNamager.AddToRole(admin.Id, "Admin");
}
where
public class ApplicationDbContext : IdentityDbContext<User>
{
public ApplicationDbContext()
: base("MyDataContext", throwIfV1Schema: false)
{
}
...
The question: If Add-Migration isn't seeing any change in the model, why do I get this error when I run? Why isn't the seed code being hit? How do I fix this, or if that can't be determined, how do I further determine the root cause?
I am not sure if you found the answer to your problem, but this other answer I found here actually did it for me:
Entity Framework model change error
I actually ended up deleting the __MigrationHistory table in SQL Server which I didn't know it was being created automatically.
The article also talks about the option to not generate it I think by using this instruction: Database.SetInitializer<MyDbContext>(null); but I have not used it, so I am not sure if it works like that
This worked for me.
Go to Package Manager Console and Run - Update-Database -force
I bet your data context is not hooking up the connection string.
Check if it's not initialized with a localdb (something like (localdb)\v11.0) and not working with that when you might think it's set to something else.
My issue ended up being a conflict between Automatic Migrations being enabled and the initializer MigrateDatabaseToLatestVersion as described here.
I have an odd one whereby increasing the value of HasMaxLength (FYI, from 200 to 500) in an EntityTypeConfiguration class seems to have no effect on the next migration that I create. I would have hoped for a modification to the column's data type length obviously.
Having discovered this I have tried adding a MaxLength attribute to the related property in my model but this had no impact on the migration created either. In both cases the migration contains empty up and down methods.
Migrations have been working flawlessly up until now. What am I missing?
Edit
To confirm, if I add an entity then I get a migration as expected with the relevant populated Up and Down methods.
As requested in comments, here is some code:
Configuration constructor:
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
DbContext constructor:
public ProjectNameContext()
: base("ProjectName")
{
Configuration.LazyLoadingEnabled = false;
}
I'm not going to post the entire config of the startup project (UI) for obvious reasons but the connection string (which is working fine) is as follows:
<add name="ProjectName" connectionString="server=.;database=ProjectName;Persist Security Info=False;MultipleActiveResultSets=true;Integrated Security=True" providerName="System.Data.SqlClient"/>
Edit 2
I've been experimenting and tried introducing a HasColumnName and the next migration has code for the column rename. If I do a HasColumnName and update the HasMaxLength then the next migration only has the rename, no change to the length. Very odd!
It would appear that the answer to the question is to upgrade Entity Framework from 6.1.0 to 6.1.1. Doing so results in a migration being created that includes the change to the HasMaxLength value. It could be a coincidence I guess but its the only change that I can attribute to the migration being created successfully.
I can't find how my connectionString syntax is wrong. Can anyone suggest a way to figure this out? I am having a difficulty using EF with my connection string. I am new to EF.
I am using Sybase Anywhere 12 database.
I'm using the Table-First ObjectContext with EDMX in a separate class library refenced by a web application.
I'm using a Ninject Module in my class library to bind my repositories.
I'm using a ODBC DataStore called "Test"
Other information EF 4.3.1.0, .NET 4, VS2010
My main web application web.config has the EF connection string copied to it as:
<connectionStrings>
<add name="Entities"connectionString="metadata=res://*/MyEntities.csdl|res://*/MyEntities.ssdl|res://*/MyEntities.msl;provider=iAnywhere.Data.SQLAnywhere;provider connection string="UserID=aUser;Password=aPassword;DataSourceName=Test"" providerName="iAnywhere.Data.SQLAnywhere"/>
</connectionStrings>
When I initialize my Entity/ObjectContext in my Repository (see using statement below) it returns an error: "The specified named connection is either not found in the configuration, not intended to be used with the EntityClient provider, or not valid."
using (var context = new Entities())
{
return {Linq to Entity here}
}
I turned on CLR exceptions on the debugger and found the code throws the error in the .NET Framework here:
EntityConnection.cs
effectiveConnectionOptions = new DbConnectionOptions(setting.ConnectionString, EntityConnectionStringBuilder.Synonyms, false);
edmx designer generated:
/// <summary>
/// Initializes a new Entities object using the connection string found in the 'Entities' section of the application configuration file.
/// </summary>
public Entities() : base("name=Entities", "Entities")
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
I can see my connection string there, so it is having a difficult time parsing the connectionString. I have tried many different permutations of syntax and haven't found anything it accepts including:
Explicitly naming the assembly for entity files instead of a wildcard(e.g. metadata=res://MyDomain/MyEntities.csdl...)
Using Sybase friendly ODBC attributes such as UID instead of UserID, PWD instead of Password, and DBN instead of DataSourceName.
Thanks.
I got everything working and the only reason I can think of is that I deleted my ASP .NET 4.0 temp files. Also, I must add I changed my process from using an integration test to test this piece to using a unit test. I did not do unit tests first, because our build server does not have a database on it.
Once I was able to prove that it was working there, I decided to delete my temp files. After that, everything started working properly. So, some sort of cache issue was occurring in my application. I used the same connectionString that I mentioned above.
Actually, I used the domain name of the Metadata "metadata=res://MyDomain/MyEntitities.csdl" rather than */MyEntities.csdl. I don't plan on changing the domain any time soon. In fact, that is just what may have caused some of the issue, because I had changed the location, name, and namespace of MyEntities.Domain where the EF was.
I want to use Entity Framework without app.config file.
I want to define a string variable Connection String in my code and use that to connect to the database.
Please show me the way if it is possible.
You're not mentioning what approach you're using (database-first, model-first, code-first) - but basically, in the end, you need to define a string variable and assign it a valid EF connection string
string myConnectionString = "...(define a valid EF connection string here)......";
Example for database-first approach:
string myConnectionString = #"metadata=.\Model1.csdl|.\Model1.ssdl|.\Model1.msl;provider=System.Data.SqlClient;provider connection string="";data source=.;initial catalog=test;integrated security=True;multipleactiveresultsets=True;App=EntityFramework""";
and then use that to create your ObjectContext (database- and model-first) or DbContext (code-first)
using(ObjectContext ctx = new ObjectContext(myConnectionString))
{
// do your EF magic here.....
}
But quite honestly - I think this is a really bad idea since this makes it impossible for you to move your application to another machine - no one else can install and run this, since the connection string is hard-coded into your C# code..... the whole point of having config files is so that you can change / adapt things like connection strings so that they are not tied to a single machine/location but can be adapted to the particular needs of a given user / customer....
I have a web forms application that uses entity framework, the application is deployed on a development box, my local machine and a production box. Each of these have different connection strings.
What is the best way of handling this.
I use TFS Build Server to deploy to development and take the result of that build zip it and copy it to production manually.
I also use Web Deployment Projects if that helps
What I was doing before was when the ORM started it would choose a connection string based on the name of the root folder. With Entity Framework I don't know how to do this without having to set it on every page.
We have something vaguely similar, I created a class to wrap the EntityContext object, which sets the connection string appropriately - you'd need something similar, based on how you set your connection string:
Public Class MyEntityModel
Private _dataContext As Entities
Public Sub New()
Dim entityBuilder As New EntityConnectionStringBuilder()
entityBuilder.ProviderConnectionString = MyApplicationConnectionString
entityBuilder.Metadata = "res://*/"
entityBuilder.Provider = "System.Data.SqlClient"
_dataContext = New Entities(entityBuilder.ConnectionString)
End Sub
Public Function DataContext() As Entities
Return _dataContext
End Function
End Class
FYI You can use config transformations now in VS 2010:
http://msdn.microsoft.com/en-us/vstudio/Video/ff801895