Programing

DbContext에 CommandTimeout을 설정하는 방법은 무엇입니까?

lottogame 2020. 12. 7. 07:43
반응형

DbContext에 CommandTimeout을 설정하는 방법은 무엇입니까?


DbContext에 CommandTimeout을 설정하는 방법을 찾고 있습니다. 검색 후 DbContext를 ObjectContext로 캐스팅하고 objectContext의 CommandTimeout 속성 값을 설정하여 방법을 찾았습니다.

var objectContext = (this.DbContext as IObjectContextAdapter).ObjectContext;

하지만 DbContext로 작업해야합니다.


귀하의 방법으로 작동합니다.

또는 하위 클래스 ( MSDN 포럼에서 )

public class YourContext : DbContext
{
  public YourContext()
    : base("YourConnectionString")
  {
    // Get the ObjectContext related to this DbContext
    var objectContext = (this as IObjectContextAdapter).ObjectContext;

    // Sets the command timeout for all the commands
    objectContext.CommandTimeout = 120;
  }
}

var ctx = new DbContext();
ctx.Database.CommandTimeout = 120;

이것은 당신을 도울 수 있습니다.

public class MyContext : DbContext
{    
    public MyContext () : base(ContextHelper.CreateConnection("my connection string"), true)
    {
        ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
    }
}

나중에 변경 사항을 잃지 않기 때문에 .tt 파일 변경이 저에게 효과적이라는 것을 알았습니다.

다음 줄을 추가하십시오.

((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;

DbContext 생성자 바로 뒤와! loader.IsLazy 구문 앞 :

<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
{
    public <#=code.Escape(container)#>()
        : base("name=<#=container.Name#>")
    {
        ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
<#
if (!loader.IsLazyLoadingEnabled(container))

그러면 생성 된 Context.cs에 나타납니다.

public MyEntities()
            : base("name=MyEntities")
        {
            ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
        }

EDMX 파일을 사용할 때이 문제를 해결 한 방법은 다음과 같습니다. 이 솔루션은 기본 T4 템플릿을 변경하여 생성 된 클래스가 기본 명령 제한 시간을 지정하는 사용자 지정 DbContext 클래스와이를 변경할 속성을 상속하도록합니다.

Visual Studio 2012 및 EF 5.0을 사용하고 있습니다. 귀하의 경험은 다른 버전과 다를 수 있습니다.

사용자 지정 DbContext 클래스 만들기

public class CustomDbContext : DbContext
{
    ObjectContext _objectContext;

    public CustomDbContext( string nameOrConnectionString )
        : base( nameOrConnectionString )
    {
        var adapter = (( IObjectContextAdapter) this);

        _objectContext = adapter.ObjectContext;

        if ( _objectContext == null )
        {
            throw new Exception( "ObjectContext is null." );    
        }

        _objectContext.CommandTimeout = Settings.Default.DefaultCommandTimeoutSeconds;
    }

    public int? CommandTimeout
    {
        get
        {
            return _objectContext.CommandTimeout;
        }
        set
        {
            _objectContext.CommandTimeout = value;
        }
    }
}

여기에는 선택적 기능이 있습니다. 기본 명령 시간 제한을 하드 코딩하지 않습니다. 대신 구성 파일의 값을 변경할 수 있도록 프로젝트 설정에서로드합니다. 프로젝트 설정을 설정하고 사용하는 방법은이 답변의 범위에 포함되지 않습니다.

또한 연결 문자열 또는 연결 문자열 이름을 하드 코딩하지 않습니다. 생성 된 컨텍스트 클래스에 의해 이미 생성자에 전달되었으므로 여기에서 하드 코딩하는 것은 의미가 없습니다. 이것은 새로운 것이 아닙니다. EDMX 파일은 이미 다음 생성자를 생성하므로 값을 전달합니다.

public MyEntities()
    : base("name=MyEntities")
{
}

(이렇게하면 EF가 구성 파일에서 "MyEntities"라는 연결 문자열을로드하도록 지시합니다.)

I'm throwing a custom exception if the ObjectContext is ever null. I don't think it ever will be, but it's more meaningful than getting a NullReferenceException.

I store the ObjectContext in a field so that I can make a property to access it to override the default.

Modifying the entity context T4 template

In the Solution Explorer, expand the EDMX file so that you see the T4 templates. They have a .tt extension.

Double click the "MyModel.Context.tt" file to open it. Around line 57 you should see this:

<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext

This template line generates the class definition of your "MyEntities" class, which inherits DbContext.

Change the line so that the generated class inherits CustomDbContext, instead:

<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : CustomDbContext

As soon as you save this file it should regenerate the class. If not, you can right-click the EDMX file and select "Run Custom Tool". If you expand the "MyModel.Context.tt" file under your EDMX file, you will see "MyModel.Context.cs". That's the generated file. Open it, and you should see that it now inherits CustomDbContext.

public partial class MyEntities : CustomDbContext

That's all there is to it.

Issues

Once you change the context class from DbContext to CustomDbContext, Visual Studio will give you an error if you try to add a new MVC controller class using the "Controller with read/write actions and views, using Entity Framework" template. It will say "Unsupported context type.". To get around this, open the generated "MyModel.Context.cs" class, and temporarily change the type it inherits back to DbContext. After adding your new controller, you can change it back to CustomDbContext.


I like the extension approach:

public static class DbContextExtensions
{
   public static void SetCommandTimeout(this ObjectContext dbContext,
       int TimeOut)
   {
       dbContext.CommandTimeout = TimeOut;
   }
}

and then simply

((IObjectContextAdapter)cx).ObjectContext.SetCommandTimeout(300);

If it can help, this is the VB.Net solution:

Dim objectContext As Objects.ObjectContext = CType(Me,IObjectContextAdapter).ObjectContext
objectContext.commandTimeout = connectionTimeout

I came here looking for an example of setting the timeout for a single command rather than such a global setting.

I figure that it will probably help someone to have an example of how I achieved this:

var sqlCmd = new SqlCommand(sql, context.Database.Connection as SqlConnection);
sqlCmd.Parameters.Add(idParam);
sqlCmd.CommandTimeout = 90;

if (sqlCmd.Connection.State == System.Data.ConnectionState.Closed)
{
    sqlCmd.Connection.Open();
}
sqlCmd.ExecuteNonQuery();
sqlCmd.Connection.Close();

참고URL : https://stackoverflow.com/questions/10549640/how-to-set-commandtimeout-for-dbcontext

반응형