使用需要超过 30 秒才能完成的函数导入时,我使用实体框架 (EF) 出现超时。我尝试了以下方法,但无法解决此问题:
我将 Default Command Timeout=300000
添加到项目的 App.Config 文件中的连接字符串中,该文件具有建议的 EDMX 文件 here。
这是我的连接字符串的样子:
<add
name="MyEntityConnectionString"
connectionString="metadata=res://*/MyEntities.csdl|res://*/MyEntities.ssdl|
res://*/MyEntities.msl;
provider=System.Data.SqlClient;provider connection string="
Data Source=trekdevbox;Initial Catalog=StarTrekDatabase;
Persist Security Info=True;User ID=JamesTKirk;Password=IsFriendsWithSpock;
MultipleActiveResultSets=True;Default Command Timeout=300000;""
providerName="System.Data.EntityClient" />
我尝试像这样直接在我的存储库中设置 CommandTimeout:
private TrekEntities context = new TrekEntities();
public IEnumerable<TrekMatches> GetKirksFriends()
{
this.context.CommandTimeout = 180;
return this.context.GetKirksFriends();
}
我还能做些什么来让 EF 避免超时?这只发生在非常大的数据集上。小数据集一切正常。
这是我遇到的错误之一:
System.Data.EntityCommandExecutionException:执行命令定义时出错。有关详细信息,请参阅内部异常。 ---> System.Data.SqlClient.SqlException:超时已过期。在操作完成之前超时时间已过或服务器没有响应。
好的 - 我得到了这个工作,发生的事情很愚蠢。我将带有 Default Command Timeout=300000
的连接字符串和 CommandTimeout 设置为 180。当我从连接字符串中删除 Default Command Timeout
时,它起作用了。因此,答案是在您的上下文对象的存储库中手动设置 CommandTimeout,如下所示:
this.context.CommandTimeout = 180;
显然在连接字符串中设置超时设置对其没有影响。
"
留在字符串中。
NONCLUSTERED
索引,这为我们解决了超时问题。
在 EF 连接字符串中指定默认命令超时存在一个已知错误。
http://bugs.mysql.com/bug.php?id=56806
从连接字符串中删除该值并将其设置在数据上下文对象本身上。如果您从连接字符串中删除冲突值,这将起作用。
实体框架核心 1.0:
this.context.Database.SetCommandTimeout(180);
实体框架 6:
this.context.Database.CommandTimeout = 180;
实体框架 5:
((IObjectContextAdapter)this.context).ObjectContext.CommandTimeout = 180;
实体框架 4 及以下:
this.context.CommandTimeout = 180;
如果您使用的是 DbContext,请使用以下构造函数来设置命令超时:
public class MyContext : DbContext
{
public MyContext ()
{
var adapter = (IObjectContextAdapter)this;
var objectContext = adapter.ObjectContext;
objectContext.CommandTimeout = 1 * 60; // value in seconds
}
}
DbContext
派生类是从 edmx
文件自动生成的,处理此问题的最佳方法是什么?
如果您使用 DbContext
和 EF v6+,或者您可以使用:
this.context.Database.CommandTimeout = 180;
通常我在事务中处理我的操作。正如我所经历的那样,设置上下文命令超时是不够的,但事务需要一个带有超时参数的构造函数。我必须设置两个超时值才能正常工作。
int? prevto = uow.Context.Database.CommandTimeout;
uow.Context.Database.CommandTimeout = 900;
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromSeconds(900))) {
...
}
在函数结束时,我将命令超时设置回 prevto 中的前一个值。
使用 EF6
如果您像我一样使用实体框架,您应该在 Startup 类上定义 Time out,如下所示:
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), o => o.CommandTimeout(180)));
我知道这是一个非常古老的线程,但 EF 仍然没有解决这个问题。对于使用自动生成的 DbContext
的人,可以使用以下代码手动设置超时。
public partial class SampleContext : DbContext
{
public SampleContext()
: base("name=SampleContext")
{
this.SetCommandTimeOut(180);
}
public void SetCommandTimeOut(int Timeout)
{
var objectContext = (this as IObjectContextAdapter).ObjectContext;
objectContext.CommandTimeout = Timeout;
}
}
在 .Net Core (NetCore) 中使用以下语法将超时从默认的 30 秒更改为 90 秒:
public class DataContext : DbContext
{
public DataContext(DbContextOptions<DataContext> options) : base(options)
{
this.Database.SetCommandTimeout(90); // <-- 90 seconds
}
}
这是我出资的。也许它会对某人有所帮助:
所以我们开始:
如果您将 LINQ 与 EF 一起使用,以查找列表中包含的一些确切元素,如下所示:
await context.MyObject1.Include("MyObject2").Where(t => IdList.Contains(t.MyObjectId)).ToListAsync();
一切正常,直到 IdList 包含多个 Id。
如果列表只包含一个 ID,就会出现“超时”问题。要解决此问题,请使用 if 条件检查 IdList 中的 id 数。
例子:
if (IdList.Count == 1)
{
result = await entities. MyObject1.Include("MyObject2").Where(t => IdList.FirstOrDefault()==t. MyObjectId).ToListAsync();
}
else
{
result = await entities. MyObject1.Include("MyObject2").Where(t => IdList.Contains(t. MyObjectId)).ToListAsync();
}
解释:
只需尝试使用 Sql Profiler 并检查 Entity frameeork 生成的 Select 语句。 …
将以下内容添加到我的存储过程中,我解决了超时错误:
SET NOCOUNT ON;
SET ARITHABORT ON;
对于实体框架 6,我使用此注释并且工作正常。
public partial class MyDbContext : DbContext
{
private const int TimeoutDuration = 300;
public MyDbContext ()
: base("name=Model1")
{
this.Database.CommandTimeout = TimeoutDuration;
}
// Some other codes
}
CommandTimeout 参数是一个可以为空的整数,它将超时值设置为秒,如果您设置为 null 或未设置,它将使用您使用的提供程序的默认值。
您可以在连接字符串中设置 2 个超时参数
超时=300;命令超时=300;
Host=localhost;Port=5432;database=mydatabase;username=postgres;password=postgres;Timeout=300;CommandTimeout=300;
一个用于命令,一个用于连接。
this.Database.SetCommandTimeout(180);