Reputation: 7038
I'm deploying a ASP.MVC 4.0 application to a Windows Server 2008 R2, with IIS 7.5, using Visual Studio 2012 web publish features. The application targets .NET 4.5, and it uses EntityFramework 5.0 Code First for data access. The target dabatase is an instance of SQL Server 2012.
In the server, I've manually created the database and users (one dbo and another with only read/write permissions) on SQL Server 2012, but not populated it. I want to use EF Migrations, using the dbo user.
In my dev workstation, everything works fine with the database targeting LocalDb, so I assume my context and mappings are right.
However, when I deploy the application to the server and try to run it, I keep getting the following exception:
System.Data.Entity.ModelConfiguration.ModelValidationException: One or more validation errors were detected during model generation:
System.Data.Entity.Edm.EdmEntityType : EntityType "Entity" has no key defined. Define the key for this EntityType.
The "EntityType has no key defined" repeats for each entity of my context.
I have checked the web.config and the connectionstrings are being deployed as expected.
The initialization of the database occurs in the Application_Start:
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, Poip.Web.Domain.Migrations.Configuration>());
using (var context = new MyContext())
context.Database.Initialize(true);
My context is simple, as my entities. I configure then with EntityTypeConfiguration classes, loading then in the context's OnModelCreating method. As I've mentioned, it works fine with LocalDb (or SqlCompact). An example of entity:
public class UserFile
{
public int UserFileKey { get; set; }
// TODO: Utilizar este campo para verificar integridade do arquivo
public string Hash { get; set; }
public string FilePath { get; set; }
public string OriginalFileName { get; set; }
public Guid Guid { get; set; }
public long Size { get; set; }
public int UserKey { get; set; }
public UserProfile User { get; set; }
public UserFile()
{
this.Guid = Guid.NewGuid();
}
}
internal class UserFileMap : EntityTypeConfiguration<UserFile>
{
public UserFileMap()
{
this.HasKey(e => e.UserFileKey);
this.Property(e => e.UserFileKey)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
this.Property(e => e.FilePath)
.IsRequired()
.HasMaxLength(255);
this.HasRequired(e => e.User)
.WithMany()
.HasForeignKey(e => e.UserKey);
}
}
My context simplified:
public class MyContext : DbContext
{
public MyContext()
{
this.Configuration.LazyLoadingEnabled = false;
}
public DbSet<UserFile> UserFiles { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Conventions.Remove<StoreGeneratedIdentityKeyConvention>();
modelBuilder.LoadConfigurations();
}
}
LoadConfigurations
is a method to load all EntityTypeConfiguration classes of the assembly. It's been tested in other applications and, again, it works on my dev workstation.
I've tried dropping Migrations entirely. I used migrations to generate a script. I removed the "__MigrationHistory" table from the script, and I executed it on the server to create the tables. Then I changed the initialization to:
Database.SetInitializer<MyContext>(null);
using (var context = new MyContext())
context.Database.Initialize(true);
But I continue to get the same exception.
I don't have any clue for what to check next. Any help would be appreciated.
EDIT
The LoadConfigurations
method:
public static void LoadConfigurations(this DbModelBuilder builder)
{
LoadConfigurations(builder, Assembly.GetCallingAssembly());
}
public static void LoadConfigurations(this DbModelBuilder builder, Assembly assembly)
{
var configurationTypes = assembly.GetTypes()
.Where(type => type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
foreach (dynamic configuration in configurationTypes.Select(type => Activator.CreateInstance(type)))
{
builder.Configurations.Add(configuration);
}
}
UPDATE
I did some tests:
I've run the application locally, "Debug" configuration, targeting LocalDb and using Migrations. The app worked with no problems. The .mdf file was created and the tables created as well.
I've published the app to the server, "Debug" configuration, targeting LocalDb and using Migrations. I've got the following yellow screen of death:
[Win32Exception (0x80004005): The system cannot find the file specified]
[SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server
I believe LocalDb is not supported by only installing Sql Server 2012.
I've published the app to the server, "Release" configuration, targeting the SQL Server 2012 database, using Migrations. The db had already been created, empty, the user specified was dbo. The error:
One or more validation errors were detected during model generation: \tSystem.Data.Entity.Edm.EdmEntityType: : EntityType 'UserFile' has no key defined. Define the key for this EntityType. [Repeats for each entity] \tSystem.Data.Entity.Edm.EdmEntitySet: EntityType: EntitySet 'UserFiles' is based on type 'UserProfile' that has no keys defined. [Repeats for each entity
I've generated a Script using Migration, send it to the server and then I executed it manually on the database. I published the app to the server, "Release" configuration, targeting SQL 2012 and using Migrations (as database initializer). Same error.
I've created an small ConsoleApplication that has a reference to my data access library. The only thing it does is to initialize the context the same way that web app does (setting the Database.SetInitializer to use migrations and creating a context). I've sent it to the server and executed it. It runs with no problems! The tables are correctly created in the database and no exception is thrown.
It seems somehow my web application is broken. I've got to find where.
Its frustrating. Why doesn't it recognize my model? I've also used NLog to check if the OnModelCreating has been hit and it had. I believe that if no metadata information was found (stored in "__MigrationHistory" table, I think), the context should trust my database.
Upvotes: 2
Views: 3072
Reputation: 7038
Finally!
Out of some feeling, I've checked the application's AppPool settings and changed "Enable 32-bit Applications" from "false" to "true" and the web application was able to access the database.
I don't know why, though, but I will try to find out.
UPDATE
Apparently I'm not the first to find errors using EntityFramework + Windows Server 2008 R2 64bits + IIS 7.5 and the "Enable 32 bits" option:
Nevertheless, in their case the symptoms were different.
Upvotes: 1
Reputation: 121599
It sounds like you're missing a primary key somewhere.
Make sure your entity has a key, make sure it's a "PROPERTY" (has get/set), and that it's "PUBLIC".
Finally, try right clicking the model, and then select 'Update Model from Database"
Links:
Upvotes: 0