ตั้งค่าการหมดเวลาฐานข้อมูลใน Entity Framework


164

คำสั่งของฉันหมดเวลาดังนั้นฉันต้องเปลี่ยนค่าการหมดเวลาคำสั่งเริ่มต้น

ฉันได้พบแต่ก็myDb.Database.Connection.ConnectionTimeoutreadonly

ฉันจะตั้งค่าการหมดเวลาของคำสั่งในEntity Framework 5 ได้อย่างไร


20
FYI, On EF6, Database.CommandTimeoutไม่ได้อ่านอย่างเดียว
itsho

2
@itsho Database.Connection.ConnectionTimeoutเขาได้รับการพูดคุยเกี่ยวกับ อย่างไรก็ตามฉันจะบอกว่านั่นDatabase.CommandTimeoutเป็นสิ่งที่ถูกต้องในกรณีที่แบบสอบถามของคุณหมดเวลา (ยกเว้นSystem.Data.Entity.Core.EntityCommandExecutionExceptionมีSystem.Data.SqlClient.SqlException: Timeout expired.)
David Ferenczy Rogožan

2
ซ้ำซ้อนที่เป็นไปได้ของEntity Framework Timeouts
Tim Pohlmann

1
ฉันคิดว่าคุณไม่สนใจเกี่ยวกับการหมดเวลาเชื่อมต่อ แต่คุณต้องการปรับการหมดเวลาของคำสั่งแทน
คุ้มค่า 7

คำตอบ:


199

ลองสิ่งนี้กับบริบทของคุณ:

public class MyDatabase : DbContext
{
    public MyDatabase ()
        : base(ContextHelper.CreateConnection("Connection string"), true)
    {
        ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 180;
    }
}

หากคุณต้องการกำหนดการหมดเวลาในสตริงการเชื่อมต่อให้ใช้Connection Timeoutพารามิเตอร์เช่นในสตริงการเชื่อมต่อต่อไปนี้:

<connectionStrings>

<add name="AdventureWorksEntities"
connectionString="metadata=.\AdventureWorks.csdl|.\AdventureWorks.ssdl|.\AdventureWorks.msl;
provider=System.Data.SqlClient;provider connection string='Data Source=localhost;
Initial Catalog=AdventureWorks;Integrated Security=True;Connection Timeout=60;
multipleactiveresultsets=true'" providerName="System.Data.EntityClient" />

</connectionStrings>

ที่มา: วิธีการ: กำหนดสตริงการเชื่อมต่อ


1
ฉันจะแนะนำให้ใช้รุ่นสตริงการเชื่อมต่อเช่นถ้าคุณพยายามที่จะเข้าถึงObjectContextในตัวสร้างนี้บางครั้งคำสั่ง PowerShell / NuGet คอนโซลจะล้มเหลวในทางที่เป็นวงกลม
Kevin Gorski

130
การเชื่อมต่อหมดเวลาและ CommandTimeout และสองสิ่งแยกกัน การตั้งค่าสตริงการเชื่อมต่อการหมดเวลาเชื่อมต่อจะไม่มีผลกับระยะเวลาที่คำสั่งรัน (CommandTimeout)
Clay Lenhart

3
ปัญหาของฉันแตกต่างเล็กน้อย ฉันหมดเวลาระหว่างการย้ายข้อมูล EF มีคุณสมบัติที่คล้ายคลึงกันซึ่งถูกตั้งค่าให้ใช้ในระหว่างการย้ายข้อมูล: msdn.microsoft.com/en-us/library/…
Karsten

2
ขึ้นอยู่กับรุ่นของ EF ที่คุณใช้ดูคำตอบนี้เพื่อรับความรู้สึกเกี่ยวกับ API ที่แตกต่างกันของวิธีการระบุคุณสมบัติ CommandTimeout
Jim Aho

1
ใช้งานไม่ได้สำหรับฉัน (Connection vs Command ไม่เหมือนเดิมฉันสงสัย) โพสต์นี้แก้ไขได้แล้วแม้ว่าstackoverflow.com/questions/6232633/entity-framework-timeouts
จัด

181

คุณสามารถใช้ได้ DbContext.Database.CommandTimeout = 180;

มันค่อนข้างง่ายและไม่จำเป็นต้องใช้นักแสดง


1
มีประโยชน์มากสำหรับเราที่ใช้Fluent APIรูปแบบของ EF
GoldBishop

20

บริบทบางส่วนของฉันดูเหมือนว่า:

public partial class MyContext : DbContext
{
    public MyContext (string ConnectionString)
        : base(ConnectionString)
    {
        this.SetCommandTimeOut(300);
    }

    public void SetCommandTimeOut(int Timeout)
    {
        var objectContext = (this as IObjectContextAdapter).ObjectContext;
        objectContext.CommandTimeout = Timeout;
    }
}

ฉันออกจากที่SetCommandTimeOutสาธารณะเท่านั้นดังนั้นกิจวัตรที่ฉันต้องใช้เวลานาน (มากกว่า 5 นาที) ฉันแก้ไขแทนที่จะหมดเวลาทั่วโลก


9

ในรหัสคอนสตรัคที่สร้างขึ้นมันควรจะเรียก OnContextCreated()

ฉันได้เพิ่มคลาสบางส่วนนี้เพื่อแก้ปัญหา:

partial class MyContext: ObjectContext
{
    partial void OnContextCreated()
    {
        this.CommandTimeout = 300;
    }
}

8

ฉันขยายคำตอบของ Ronnie ด้วยการนำไปใช้อย่างคล่องแคล่วเพื่อให้คุณสามารถใช้งานได้เช่น:

dm.Context.SetCommandTimeout(120).Database.SqlQuery...

public static class EF
{
    public static DbContext SetCommandTimeout(this DbContext db, TimeSpan? timeout)
    {
        ((IObjectContextAdapter)db).ObjectContext.CommandTimeout = timeout.HasValue ? (int?) timeout.Value.TotalSeconds : null;

        return db;
    }

    public static DbContext SetCommandTimeout(this DbContext db, int seconds)
    {
        return db.SetCommandTimeout(TimeSpan.FromSeconds(seconds));
    } 
}

8

สำหรับฐานข้อมูล Aproach แรก:

เรายังคงสามารถตั้งค่าได้ในนวกรรมิกโดยแทนที่ContextName.Context.ttเทมเพลต T4 ด้วยวิธีนี้:

<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
{
    public <#=code.Escape(container)#>()
        : base("name=<#=container.Name#>")
    {
        Database.CommandTimeout = 180;
<#
if (!loader.IsLazyLoadingEnabled(container))
{
#>
        this.Configuration.LazyLoadingEnabled = false;
<#
}

Database.CommandTimeout = 180; เป็นการเปลี่ยนแปลงที่แท้จริง

ผลลัพธ์ที่สร้างขึ้นคือ:

public ContextName() : base("name=ContextName")
{
    Database.CommandTimeout = 180;
}

หากคุณเปลี่ยนโมเดลฐานข้อมูลเทมเพลตนี้จะยังคงอยู่ แต่คลาสจริงจะได้รับการอัปเดต


มีวิธีที่เราสามารถระบุการหมดเวลาในเทมเพลตโดยใช้ไฟล์กำหนดค่าบางไฟล์หรือไม่?
shas

1
ไม่แน่ใจว่ามีบางอย่างในตัว (ฉันไม่สามารถหาอะไรได้) แต่แทนที่จะเป็น hardcoding 180 คุณสามารถใช้System.Configuration.ConfigurationManager.AppSettings["keyname"]@shas
Christian Gollhardt

7

เหมือนกับคำตอบอื่น ๆ แต่เป็นวิธีการขยาย:

static class Extensions
{
    public static void SetCommandTimeout(this IObjectContextAdapter db, TimeSpan? timeout)
    {
        db.ObjectContext.CommandTimeout = timeout.HasValue ? (int?) timeout.Value.TotalSeconds : null;
    }
}

และฉันจะเรียกวิธีการส่วนขยายนี้ได้อย่างไร
Wanderson López

1

ฉันเพิ่งพบปัญหานี้และแก้ไขได้โดยอัปเดตไฟล์การกำหนดค่าแอปพลิเคชันของฉัน สำหรับการเชื่อมต่อที่สงสัยให้ระบุ "การเชื่อมต่อหมดเวลา = 60" (ฉันกำลังใช้เฟรมเวิร์กเอนทิตีเวอร์ชัน 5.0.0.0)

การตั้งค่า ConnectionTimeout


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.