2

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.

Community
  • 1
  • 1
Arthur Nunes
  • 6,718
  • 7
  • 33
  • 46
  • Can you show us one of your class throwing this error? I want to check if you are using `Id`, `EntityId` or `[Key]` in your entities. – glautrou Aug 27 '13 at 17:08
  • Can you show the `LoadConfiguration` method? Apparently for some reason it doesn't work. – Wiktor Zychla Aug 27 '13 at 17:44
  • Could this be a Full Trust (Dev environment) vs. Medium (or lower) Trust (Live environment) thing? Maybe the reflection in `LoadConfigurations` doesn't work properly then. I'm not sure, only a very vague hypothesis... – Slauma Aug 27 '13 at 18:36
  • @Slauma, please take a look on my last test in the edit. – Arthur Nunes Aug 27 '13 at 18:49
  • Well, the trust level settings (usually in machine.config in the .NET install dir) are ASP.NET settings, so a console app can run while a web app doesn't. Is this "your" server or is it a hosting provider's server? I would add some debug code into `LoadConfigurations`, like writing the configuration type names that the `foreach` loop is iterating through into a text file. The exception really looks like adding the configurations to the model builder is failing for some reason. – Slauma Aug 27 '13 at 19:08

2 Answers2

1

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:

Here Here

Nevertheless, in their case the symptoms were different.

Community
  • 1
  • 1
Arthur Nunes
  • 6,718
  • 7
  • 33
  • 46
0

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:

Community
  • 1
  • 1
paulsm4
  • 114,292
  • 17
  • 138
  • 190
  • Paul, I use CodeFirst and the POCOs and configurations were all created by me. Also, it works fine on my dev workstation, with LocalDb (or SQL CE). I have created other applications using EF Code First. I have a local app (WPF) running fine with Code First and Migrations. – Arthur Nunes Aug 27 '13 at 17:30