【发布时间】:2016-10-10 04:45:09
【问题描述】:
我们正在开发一个可以管理多个客户端的 WPF 应用程序。对于每个客户端,我们需要一个单独的数据库(在同一个 SQL Server 实例中)。所以我们需要不止一次“创建数据库”。所有单独的客户端数据库都将具有相同的数据库结构。
我们使用实体框架版本 6.1.3、代码优先和 SQL Server 2014 Express 的本地安装。在我们的“真实”业务应用程序中,正确创建了一个包含大约 60 个表的新数据库,但性能不是很好。
为了找出问题,我编写了一个小示例程序,它在一个循环中创建 5 个数据库,每个数据库 1 个表。在我的 Dev-PC(Windows 10、i7-6700 3.40GHz、16 GB RAM)上,这 5 个数据库的执行时间约为 1 分钟(每个数据库为 11-12 秒)。调试应用的时候,看到在线等待很长时间
dbContext.Database.CreateIfNotExists();
在 SQL Server Profiler 中,我看到每个循环大约需要 10 秒,直到第一个条目到达。
知道时间在哪里浪费了吗?或者在实体框架中使用相同的 DbContext 创建多个数据库(> 20 个)的其他建议?
这里是我的示例应用程序的源代码:。
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System;
namespace TestEnityFramework01.Model
{
[Table("Table01")]
public class Table01 {
[Key]
[Column("ID", Order = 0, TypeName = "int")]
public int ID { get; set; }
[Column("Number01", TypeName = "int")]
public int Number01 { get; set; }
[Column("Date01")]
public DateTime? Date01 { get; set; }
[StringLength(50)]
[Column("Text01", TypeName = "nvarchar")]
public string Text01 { get; set; }
[Column("Amount01")]
public decimal Amount01 { get; set; }
[Column("Doule01")]
public double Doule01 { get; set; }
[Column("Bool01")]
public bool Bool01 { get; set; }
}
}
还有上下文:
using TestEnityFramework01.Model;
using System.Data.Entity;
namespace TestEnityFramework01.Context
{
class ContextA : DbContext
{
public DbSet<Table01> Tabel01 { get; set; }
public ContextA()
: base("ContextA")
{
// Don't create database automatically
Database.SetInitializer<ContextA>(null);
}
public ContextA(string pConnectionString)
: base(pConnectionString)
{
// Don't create database automatically
Database.SetInitializer<ContextA>(null);
this.Configuration.AutoDetectChangesEnabled = false;
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.ValidateOnSaveEnabled = false;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
}
测试程序循环生成五个数据库:
private void button_Click(object sender, RoutedEventArgs e)
{
int _randomNumber = 0;
for (int i = 1; i <= 5; i++)
{
// create random number between 1 and 100'000
_randomNumber = new Random().Next(1, 100000);
// concat the random number to the database name
string _databaseName = "DatabaseCustomer" + _randomNumber.ToString();
// the connection-string look like this:
// "Data Source=MyPC\SQLEXPRESS;Initial Catalog=MyDatabaseName;User ID=MyUser;Password=MyPassword;Integrated Security=False;MultipleActiveResultSets=True;"
string _connectionString = GetConnectionString(_databaseName);
using (var dbContext = new ContextA(_connectionString))
{
// create the database
dbContext.Database.CreateIfNotExists();
}
}
}
**** 2016 年 6 月 16 日更新**** 当我将数据库连接从 SQL-Server 2014 Express 切换到“SQL Server Compact Edition”时,所有 5 个数据库的创建时间大约为 1 或 2 秒。可能是我使用错误的连接字符串连接 sql-server 还是我的 SQL-Server 2014 Express 配置不正确?
【问题讨论】:
-
出于好奇,您正在创建的 .mdf 和 .ldf 文件有多大?似乎默认值应该是 3 兆和 1 兆,但它们在您的测试用例中有多大?
-
.mdf 文件大小为 4'288 KB,.ldf 文件大小为 1072 KB。
-
您确定
Database.SetInitializer<ContextA>(null);在您的代码中的位置吗?似乎天真地瞥了一眼您在初始化程序内部设置数据库初始化程序的代码,这似乎是错误的(可能是递归问题)。在在线示例中,我看到 setInitializer 发生在代码的配置部分。 -
当 EF 尝试通过尝试连接来检查数据库是否存在时,我们看到了类似的 10 秒延迟,这是由 SqlClient 自己的连接弹性功能启动引起的。如果这导致您的方案出现延迟,您应该能够通过将 ConnectRetryCount=0 添加到连接字符串来改进。
-
是的,你是对的。通过将 ConnectRetryCount=0 添加到连接字符串大约快十倍。非常感谢
标签: sql-server database performance ef-code-first entity-framework-6