I am using EF 4.1, and I create a normal EF edmx file.
I generate it from a DB.
When it's been generated I rightclick and select add code generation item, to generate new classes, and use the DbContext instead. I use the template DbContext generator.
Everything works fine.
Then I trie to query the context:
using (var context = new PasDBEntities())
{
var client=context.ClientCompanies.SingleOrDefault(_=>_.ID==clientCompanyId);
if(client!=null)
I have no problem creating a new instance of the context but when I try to query it the problem occur. I get stuck on the UnintentionalCodeFirstException.
And gets the error:
{"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."}
I don't want to use code first, but I don't know if I can "switch" it off, or where the problem is.
For reference, here is my constructor ...
public partial class PasDBEntities : DbContext
{
public PasDBEntities()
: base("PasDBEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
...and connection string:
<connectionStrings>
<add name="PasDBEntities"
connectionString="metadata=res://*/PasDB.csdl|
res://*/PasDB.ssdl|
res://*/PasDB.msl;
provider=System.Data.SqlClient;
provider connection string="
data source=localhost;
initial catalog=PasDB;
integrated security=True;
pooling=False;
multipleactiveresultsets=True;
App=EntityFramework""
providerName="System.Data.EntityClient" />
</connectionStrings>
I see you are using the EDMX with Templates (.tt) for generating the classes. But if you are getting the information from a existing database, the wizard will create a ConnectionString compatible with ObjectContext (metadata informations and provider of entityframework).
The problem is that the connectionstring you are using is for ObjectContext (Database First and Model First). For the DbContext you should use the connectionstring without the metadata informations.
Your connection string should be:
<connectionStrings>
<add name="PasDBEntities"
connectionString="data source=localhost;
initial catalog=PasDB;
integrated security=True;
pooling=False;
multipleactiveresultsets=True;
App=EntityFramework"
providerName="System.Data.SqlClient" />
Related
I have the following in my code:
DbContext = new DataContext();
DbContext.Configuration.AutoDetectChangesEnabled = false;
Then in my controller method:
// GET /api/Applications
public IEnumerable<Application> Get()
{
return _uow.Applications.GetAll().OrderBy(p => p.Name);
}
However I still get the following message:
System.InvalidOperationException was unhandled by user code
HResult=-2146233079
Message=The model backing the 'DataContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).
Source=EntityFramework
StackTrace:
Can someone explain why this is happening. I thought the line after my context creation would stop this check.
You can place (it's a static method)
Database.SetInitializer<DataContext>(null);
before you first use your DataContext. But take a note, that this will turn it off. Done. If your database is not compatible with model, your queries etc. will fail.
This is because you have some difference in database schema with your entity mode. The error is saying that you need to update the database schema according to the new model you have in the code.
AutoDetectChangesEnabled is not something related to this error. Because it is about tracking changes to the data while the error you are getting is related to the changes in database schema .
The error message is suggesting you to use code first migrations to update the database schema according to your changes in data model.
You have 2 options:
1. Set the Initializer of your context to null by placing this line in the constructor of your derived DbContext:
Database.SetInitializer<MyContext>(null);
2. Disable the Database Initializer in your Web.config file by adding a Key inside the appSettings node:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="DatabaseInitializerForType YourNamespace.YourDbContext, YourAssemblyName"
value="Disabled" />
</appSettings>
</configuration>
Replace YourNamespace.YourDbContext and YourAssemblyName with the corresponding value in your application.
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 have two databases. When I make a change to one of my dbcontext (adding a new DbSet) it should automatically apply the changes to the correct databases when runnnig my webapplication. So the new table should be added. Therefore I have added two configuration classes. One for each database/context.
However using the initializers like below the changes are always applied to the second context/database. Because this is the latest initializer configured.
Database.SetInitializer(new MigrateDatabaseToLatestVersion<DomainReadModelContext, DomainConfiguration>());
Database.SetInitializer(new MigrateDatabaseToLatestVersion<WebsiteReadModelContext, WebsiteConfiguration>());
I also tried it in the web.config
<contexts>
<context type="Domain.ReadModels.DomainReadModelContext, Domain.ReadModels">
<databaseInitializer type="System.Data.Entity.MigrateDatabaseToLatestVersion`2[[Domain.ReadModels.DomainReadModelContext, Domain.ReadModels], [Website.Migrations.Domain.DomainConfiguration, Website-WebAppMainModule, Version=1.0.0.0, Culture=neutral]], EntityFramework" />
</context>
<context type="Website.ReadModels.WebsiteReadModelContext, Website.ReadModels">
<databaseInitializer type="System.Data.Entity.MigrateDatabaseToLatestVersion`2[[Website.ReadModels.WebsiteReadModelContext, Website.ReadModels], [Website.Migrations.Website.WebsiteConfiguration, Website-WebAppMainModule, Version=1.0.0.0, Culture=neutral]], EntityFramework" />
</context>
</contexts
When applying the changes via the package manager it works as it should be. The table gets added to my domaincontext database.
Update-Database -config DomainConfiguration
Is this because this isn't supported or am I doing it wrong? Now it seems to work only for the latest initializer registered.
For the update I have scaffolded a Migration using the Add-Migration command in the package manager.
Add-Migration AddUniquePersonReadModelMigration -config DomainConfiguration
This generated following class for me.
public partial class AddUniquePersonReadModelMigration : DbMigration
{
public override void Up()
{
CreateTable(
"UniquePersonReadModels",
c => new
{
Id = c.Guid(nullable: false, identity: true),
PersonId = c.Guid(nullable: false),
DisplayName = c.String(maxLength: 128),
})
.PrimaryKey(t => t.Id)
.Index(p => p.PersonId)
.Index(p => p.DisplayName, true);
}
public override void Down()
{
DropIndex("UniquePersonReadModels", new[] { "PersonId" });
DropIndex("UniquePersonReadModels", new[] { "DisplayName" });
DropTable("UniquePersonReadModels");
}
}
So my question is does entity framework support the migrations for multiple contexts using initializers? If not, it would be a nice feature when the migrations can be handled for multiple contexts.
I have solved the problem by moving the Migration folder from my website to separate assemblies.
So instead of the following:
Solution/
DomainReadModels/
DomainContext.cs
Classes........
WebsiteReadModels/
WebsiteContext.cs
Classes........
Website/
Migration/
AddSomeTableToDomainMigration.cs
AddSomeTableToWebsiteMigration.cs
WebsiteReadModelsConfiguration.cs
DomainReadModelsConfiguration.cs
Websitefiles...
I changed my solution to:
Solution/
DomainReadModels/
Migration/
DomainReadModelsConfiguration.cs
AddSomeTableToDomainMigration.cs
DomainContext.cs
Classes........
WebsiteReadModels/
Migration/
AddSomeTableToWebsiteMigration.cs
WebsiteReadModelsConfiguration.cs
WebsiteContext.cs
Classes........
Website/
Websitefiles...
Now the only disadvantage is I have to switch projects in the package manager console...
If I understand your question correctly you are using two contexts DomainReadModelContext and WebsiteReadModelContext and each of these contexts uses a different database. If this is the case, then you can certainly have an initializer for each context and it will be run the first time that context is used against the given database. In other words, the initializer for DomainReadModelContext will be run the first time that DomainReadModelContext is used against the domain model database, and the initializer for WebsiteReadModelContext will be run the first time that WebsiteReadModelContext is used against the domain model database.
If both contexts are using the same database then this will not work. Using Migrations for multiple contexts that access the same database is not supported in EF5, but we're working on it for EF6.
I have several databases, the schema of them are same. When I use database-first, the connection string is specified when I create the edmx file. I want to know, is there a way to change the connection string? This is, so I can choose which database to operate.
We do not store connection strings in our web.configs, so the accepted solution would not work for us. If you simply attempt to provide the connection string via the base DbContext constructor, you'll get the following exception:
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.
To resolve this, create a partial class of your context as follows and format your connection string with the additional EF metadata (where MyContext is your context model name (e.g. your model name is MyModel.edmx, than the MyContext in code below is replaced with MyModel with all three extensions .csdl, .ssdl, .msl used)):
public partial class MyContext
{
public MyContext(string connStr)
: base(string.Format(#"metadata=res://*/MyContext.csdl|res://*/MyContext.ssdl|res://*/MyContext.msl;provider=System.Data.SqlClient;provider connection string='{0}'", connStr))
{
}
}
Change the connection string in the web.config file.
<connectionStrings>
<add name="SandBoxEntities" connectionString="metadata=r... />
</connectionStrings>
I abbreviated the actual connection string because it isn't important -- just wanted to give you an idea of what to look for in the web.config file.
You can also change your connection strings programatically. Check out Example 16.2. Programmatically modifying an EntityConnectionString.
You can define multiple connection string in web.config and then use them in your code perhaps your job.
for example:`
<connectionStrings>
<add name="conStr1" connectionString="metadata=r... />
</connectionStrings>`
<connectionStrings>
<add name="conStr2" connectionString="metadata=r... />
</connectionStrings>`
and so on
and your context class constructor get connection string name as parameter:
public MyContext(string connStr)
: base(connStr) { }
Ok. now you can use in your code as below:
using (var db = new MyContext("name=conStr1"))
{
//your code here
}
and then
using (var db = new MyContext("name=conStr2"))
{
//your code here
}
I'm working through the Building an MVC 3 App with Code First and Entity Framework 4.1 tutorial on MSDN and got stuck on "Also by default, this database will be a SQL Express database with the name derived from the strongly typed name of the context and its file will be in the SQL Express default data folder."
If I want to change the default (e.g. to place the MDF file in my App_Data folder) how would I do that? I will have several different contexts (one for each major functional area) and would like them all to live in the same database.
You define where the database lives using the web.config file connection settings.
You just have to make the Context Name = your connection string name so if the of you Context is MyContext you could define the location as below:
<connectionStrings>
<clear/>
<add name="MyContext"
connectionString="Server=myServer;Database=MyDB;Uid=foo;Password=XXX; "
providerName="System.Data.SqlClient"
/>
</connectionStrings>
In answer to your second question...
"I will have several different contexts (one for each major functional area) and would like them all to live in the same database."
Why not try...
MyContext.cs
public partial class MyContext : DbContext
{
}
FooContext.cs
partial class MyContext
{
public DbSet<Foo> Foos { get; set; }
}
BarContext.cs
partial class MyContext
{
public DbSet<Bar> Bars { get; set; }
}
You'll end up with one context and one connection, but your code is split over multiple files. Hopefully that's what you are trying to achieve.