Entity Framework Code-First非常缓慢。

3

根据广泛的谷歌搜索,似乎我不是第一个遇到这个问题的人,但我一直找不到任何人能够令人满意地解决它 - 我正在集成一个传统数据库,并且我只尝试与单个表进行集成(目前)但我的第一个对这个模型的查询需要大约12秒左右才能执行。但预计第二个调用将几乎立即完成。

以下是我整体的Entity Framework Code First设置:

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");
    }
}

这段代码示例需要执行8-12秒:

    PortalDatabase database = new PortalDatabase();

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

我了解这个问题与元数据生成有关,这只需要进行一次,根据 ScottGu的评论,“可以大大提高性能”:

“Code First”库使用与传统方法相同的EF作为其基础,因此性能特征应该大致相同。 “Code First”库还包括一些智能功能,以便对于从数据库映射/映射而来的元数据进行缓存-这样它只需要计算一次(这大大提高了性能)。

但是我描述的性能是否平均?我无法想象执行简单查询需要12秒钟的时间会被Entity Framework团队接受。我是否误解了他?元数据缓存是否在例如IIS应用程序池的生命周期内保持不变?这可能在某种程度上是可以接受的,虽然仍然不理想。
如果我不使用代码优先,那么我就可以使用EdmGen.exe生成我的视图,据我所知这会使我的应用程序更快。在使用代码优先开发模型时是否有相应的方法?

2012年2月14日更新: 多亏了Pawel的帖子,我能够生成我的视图。不幸的是,这并没有改变创建新PortalDatabase实例的速度,仍然需要同样长的时间。我知道视图正在被使用,因为我在构造函数中设置了断点,但这并不影响任何事情。

元数据缓存存在于一个 AppDomain 的生命周期内。元数据加载较慢,但对于这样一个简单模型来说,12秒实在太慢了。 - Slauma
我已将你的模型复制到控制台应用程序中,并创建了一个空数据库(由EF自动完成)。第一个查询花费了1秒钟,第二个查询立即返回。这12秒很奇怪... - Slauma
1个回答

2

非常感谢!我已经成功生成了视图,但不幸的是这并没有产生任何影响。您还有其他想法吗? - Steve Rukuts
你确定是什么导致了这个问题吗?是只有第一个查询很慢还是所有的查询都很慢?如果只有查询很慢,那么很可能是以下两种情况之一 - 视图生成(对于小模型不应该发生)或者创建数据库(如果不存在)。当数据库存在时,你是否看到了这种缓慢的情况?此外,你尝试过手动连接数据库吗?速度快吗?如果所有查询都出现这种情况 - 你可以尝试使用Sql Profiler来查看执行查询所需的时间。另外,你是否使用了任何更高级的映射,例如层次结构或实体拆分? - Pawel
如果您的模型像上面那样简单,那么您不应该从EF/CodeFirst中期望太多性能下降。对于这种类型的模型,我会关注网络/数据库。 - Pawel
好的,我根本没有创建数据库,目前是连接到我的本地机器上的SQL服务器实例。幸运的是,在第一次请求我的WCF服务后,它所做的任何事情都会被缓存,所以我可以继续而不必担心这会在生产中引起问题。不过我真的希望我的单元测试能跑得更快些。 - Steve Rukuts

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接