Arthur Nunes
Arthur Nunes

Reputation: 7038

Error using Entity Framework 5 with SQL Server 2012

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:

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

Answers (2)

Arthur Nunes
Arthur Nunes

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:

Here Here

Nevertheless, in their case the symptoms were different.

Upvotes: 1

paulsm4
paulsm4

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

Related Questions