[c#] 엔터티 프레임 워크 시간 초과

완료하는 데 30 초 이상 걸리는 함수 가져 오기를 사용할 때 Entity Framework (EF)를 사용하여 시간 초과가 발생합니다. 다음을 시도했지만이 문제를 해결할 수 없었습니다.

여기에 제안 된대로 EDMX 파일이있는 프로젝트 Default Command Timeout=300000App.Config 파일에 연결 문자열을 추가 했습니다 .

내 연결 문자열은 다음과 같습니다.

<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 : 시간 초과가 만료되었습니다. 작업이 완료되기 전에 시간 초과 기간이 경과했거나 서버가 응답하지 않습니다.


OK-나는이 일을했고 바보 일이 일어났습니다. 연결 문자열이 Default Command Timeout=300000있고 CommandTimeout이 180으로 설정되었습니다 Default Command Timeout. 연결 문자열에서 연결 문자열을 제거하면 작동했습니다. 따라서 정답은 컨텍스트 객체의 저장소에서 CommandTimeout을 수동으로 설정하는 것입니다.

this.context.CommandTimeout = 180;

연결 문자열에서 시간 초과 설정을 설정해도 영향을 미치지 않습니다.



답변

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;

Entity Framework 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
    }
}


답변

DbContextEF 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 사용


답변

나는 이것이 매우 오래된 스레드 실행이라는 것을 알고 있지만 여전히 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;
    }


답변

나와 같은 Entity Framework를 사용하는 경우 다음과 같이 시작 클래스에서 시간 초과를 정의해야합니다.

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


답변

이것이 내가 투자 한 것입니다. 어쩌면 누군가에게 도움이 될 것입니다.

그래서 우리는 간다 :

EF와 함께 LINQ를 사용하면 다음과 같이 목록에 포함 된 정확한 요소를 찾습니다.

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 문을 확인하십시오. …