实体框架超时

本文关键字:超时 框架 实体 | 更新日期: 2023-09-27 17:58:18

使用需要 30 秒以上才能完成的函数导入时,使用实体框架 (EF( 时出现超时。我尝试了以下方法,但无法解决此问题:

我按照此处的建议,向具有 EDMX 文件的项目中的 App.Config 文件中的连接字符串添加了Default Command Timeout=300000

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

<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 的连接字符串和命令超时都设置为 180。当我从连接字符串中删除Default Command Timeout时,它起作用了。所以答案是在上下文对象的存储库中手动设置 CommandTimeout,如下所示:

this.context.CommandTimeout = 180;

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

实体框架超时

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

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 和 EF v6+,也可以使用:

this.context.Database.CommandTimeout = 180;

如果您像我一样使用实体框架,则应按如下方式定义启动类超时:

 services.AddDbContext<ApplicationDbContext>(
   options => options.UseSqlServer(
     Configuration.GetConnectionString("DefaultConnection"), 
     a => a.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

.NET Core 中,使用以下语法将超时从默认的 30 秒更改为 90 秒:

public class DataContext : DbContext
{
    public DataContext(DbContextOptions<DataContext> options) : base(options)
    {
        this.Database.SetCommandTimeout(90); // <-- 90 seconds
    }
}
我知道

这是运行非常旧的线程,但 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;
    }
}

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

所以我们来了:

如果将 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语句。

对于实体框架 6,我使用此注释并且工作正常。

  public partial class MyDbContext : DbContext
  {
      private const int TimeoutDuration = 300;
      public MyDbContext ()
          : base("name=Model1")
      {
          this.Database.CommandTimeout = TimeoutDuration;
      }
       // Some other codes
    }

命令超时参数是设置超时的可为空的整数值为秒,如果设置 null 或未设置,将使用默认值您使用的提供程序的值。

将以下内容添加到我的存储过程中,解决了超时错误:

SET NOCOUNT ON;
SET ARITHABORT ON;

对于 Postgres SQl 用户,根据此处的文档 - https://www.npgsql.org/doc/connection-string-parameters.html

可以在连接字符串中设置 2 个超时参数

超时 = 300;命令超时 = 300;

Host=localhost;Port=5432;database=mydatabase;username=postgres;password=postgres;Timeout=300;CommandTimeout=300;
一个

用于命令,一个用于连接。