提问



在使用需要超过30秒才能完成的函数导入时,我正在使用实体框架(EF)获得超时。我尝试了以下操作,但无法解决此问题:


我将Default Command Timeout=300000添加到项目中 App.Config 文件中的连接字符串中,该文件具有此处建议的EDMX文件。


这是我的连接字符串的样子:


<add 
    name="MyEntityConnectionString" 
    connectionString="metadata=res://*/MyEntities.csdl|res://*/MyEntities.ssdl|
       res://*/MyEntities.msl;
       provider=System.Data.SqlClient;provider connection string=&quot;
       Data Source=trekdevbox;Initial Catalog=StarTrekDatabase;
       Persist Security Info=True;User ID=JamesTKirk;Password=IsFriendsWithSpock;
       MultipleActiveResultSets=True;Default Command Timeout=300000;&quot;"
    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;


显然在连接字符串中设置超时设置对它没有影响。

最佳参考


在EF连接字符串中指定默认命令超时存在已知错误。


http://bugs.mysql.com/bug.php?id=56806[21]


从连接字符串中删除值并将其设置在数据上下文对象本身上。如果从连接字符串中删除冲突的值,这将起作用。


实体框架核心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;

其它参考1


如果您使用的是DbContext,请使用以下构造函数来设置命令超时:


public class MyContext : DbContext
{
    public MyContext ()
    {
        var adapter = (IObjectContextAdapter)this;
        var objectContext = adapter.ObjectContext;
        objectContext.CommandTimeout = 1 * 60; // value in seconds
    }
}

其它参考2


如果您使用DbContext和EF v6 +,您可以使用:


this.context.Database.CommandTimeout = 180;

其它参考3


通常我会在交易中处理我的操作。正如我所经历的那样,设置上下文命令超时是不够的,但是事务需要一个带有超时参数的构造函数。我必须设置两个超时值才能正常工作。


int? prevto = uow.Context.Database.CommandTimeout;
uow.Context.Database.CommandTimeout = 900;
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromSeconds(900))) {
...
}


在函数结束时,我将命令超时设置为prevto中的先前值。


使用EF6

其它参考4


我知道这是非常老的线程运行,但仍然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;
    }

其它参考5


这就是我所资助的。也许它会对某人有所帮助:


所以我们走了:


如果您使用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并检查实体frameeork生成的Select语句。 ...


其它参考6


如果你像我一样使用Entity Framework,你应该在Startup类上定义Time out,如下所示:


 services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), o => o.CommandTimeout(180)));