Entity Framework Code-First is very slow

2019-04-01 03:12发布

问题:

From extensive googling, it would appear that I'm not the first person to encounter this problem, but I have been unable to find anyone who was able to satisfactorily solve it - I am integrating with a legacy database, and I am only attempting to integrate with a single table (at the moment) and yet my first query to this model takes about 12 seconds or so to execute. The second call is almost instant though, as expected.

What follows is the entirety of my Entity Framework Code First setup:

public class PortalDatabase : DbContext
{
    public DbSet<User> Users { get; set; }

    public PortalDatabase():base("portalDatabase")
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        User.ConfigureEntity(modelBuilder.Entity<User>());
    }
}

public class User
{
    public int ID { get; set; }

    public string FullName { get; set; }

    /// <summary>
    /// Internal representation of the IsDisabled flag. This should not be
    /// written to; use <see cref="IsDisabled"/> instead.
    /// </summary>
    internal byte IsDisabledInternal { get; set; }

    public bool IsDisabled
    {
        get { return Convert.ToBoolean(this.IsDisabledInternal); }
        set { this.IsDisabledInternal = Convert.ToByte(value); }
    }

    public int LoginAttempts { get; set; }

    public string EmailAddress { get; set; }

    public string Password { get; set; }

    internal static void ConfigureEntity(EntityTypeConfiguration<User> entity)
    {
        entity.ToTable("Users");

        entity.Property(model => model.ID)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
            .HasColumnName("UserID");

        entity.Property(model => model.FullName)
            .HasColumnName("UserName");

        entity.Property(model => model.IsDisabledInternal)
            .HasColumnName("AccountLocked");

        entity.Ignore(model => model.IsDisabled);

        entity.Property(model => model.LoginAttempts)
            .HasColumnName("LoginAttempts");

        entity.Property(model => model.EmailAddress)
            .HasColumnName("EmailAddress");

        entity.Property(model => model.Password)
            .HasColumnName("Password");
    }
}

This code sample takes 8-12 seconds to execute:

    PortalDatabase database = new PortalDatabase();

    IEnumerable<User> users = from user in database.Users
                              where user.ID == 66
                              select user;

I understand that this issue is to do with metadata generation, which is done only once, which according a comment from ScottGu "improves performance a lot":

The "code first" library uses the same underlying EF as the traditional approach - so the performance characteristics should be about the same. The "code first" library also includes aome smarts so that the meta-data that is retrieved for mapping to/from the database is cached - so that it only needs to be calculated once (which improves performance a lot).

But is the performance I have described average? I can't imagine that taking 12 seconds to execute a simple query would ever be acceptable to the Entity Framework team. Am I misunderstanding him? Does the metadata cache persist for the lifetime of, for example, an IIS application pool? That might be in some way acceptable, although still hardly ideal.

If I wasn't using code first, then I'd be able to use EdmGen.exe to generate my views, which as I understand it would make my application considerably faster. Is there an equivalent when developing my model using code first?

Update 14th Feb 2012: Thanks to Pawel's post, I was able to generate my views. Unfortunately, this has not changed the speed of creating a new PortalDatabase instance, which still takes the same amount of time. I know that the views are being used because I put a breakpoint in the constructor, but this doesn't affect anything.

回答1:

To generate views with CodeFirst use EF Power Tools. See more details here: http://blogs.msdn.com/b/adonet/archive/2011/05/18/ef-power-tools-ctp1-released.aspx