Varlık Çerçevesi Zaman Aşımları


324

Tamamlanması 30 saniyeden fazla süren bir işlev içe aktarma kullanırken Entity Framework (EF) kullanarak zaman aşımları alıyorum. Aşağıdakileri denedim ve bu sorunu çözemedim:

Burada önerildiği gibi EDMX dosyasına sahip projedeki App.Config dosyasındaki Default Command Timeout=300000bağlantı dizesine ekledim .

Benim bağlantı dizesi böyle görünüyor:

<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" />

Benim depoda CommandTimeout ayarını doğrudan böyle denedim:

private TrekEntities context = new TrekEntities();

public IEnumerable<TrekMatches> GetKirksFriends()
{
    this.context.CommandTimeout = 180;
    return this.context.GetKirksFriends();
}

EF'in zaman aşımına uğraması için başka ne yapabilirim? Bu yalnızca çok büyük veri kümeleri için olur. Her şey küçük veri kümeleriyle iyi çalışır.

İşte aldığım hatalardan biri:

System.Data.EntityCommandExecutionException: Komut tanımı yürütülürken bir hata oluştu. Ayrıntılar için iç istisnayı inceleyin. ---> System.Data.SqlClient.SqlException: Zaman aşımı süresi doldu. İşlemin tamamlanmasından önce geçen zaman aşımı süresi veya sunucu yanıt vermiyor.


Tamam - bu işi aldım ve olan bu saçma. Ben hem bağlantı dizesi vardı Default Command Timeout=300000ve CommandTimeout 180 olarak ayarlanmış. Default Command TimeoutBağlantı dizesinden kaldırdığımda işe yaradı. Bu nedenle yanıt, deponuzdaki CommandTimeout'u içerik nesneniz üzerinde manuel olarak şu şekilde ayarlamaktır:

this.context.CommandTimeout = 180;

Görünüşe göre bağlantı dizesinde zaman aşımı ayarlarını yapmanın herhangi bir etkisi yoktur.


Kaldır & quot; bağlantı dizesinden
Brian Webster


5
@ hamlin11 Bir EF bağlantı dizesinde, hangi parçanın bağlantı dizesi ve hangi parçanın EF meta verileri olduğunu tanımlamak gerekir. Dizgide bırakın &quot;.
Chev

2
benim önerim, zaman aşımını artırmadan önce EF'nin neden zaman aşımına uğradığını görmek için araştırmak olacaktır. Bizim durumumuzda NONCLUSTEREDbazı tablolara indeks eklememiz gerektiğini fark ettik , bu bizim için zaman aşımı sorununu çözdü.
zulucoda

MS desteği ile bir SQL zaman aşımı sorunu üzerinde çalışıyorum - bu DB SQL Azure barındırılan zaman. Tüm Azure PaaS hizmetlerinin (PaaS web siteleri ve SQL Azure vb.) 230 saniyelik evrensel bir zaman aşımı olduğu söylendi ve manuel olarak bir zaman aşımı ayarlasanız bile bu her zaman önceliklidir. Bu, çok kiracılı PaaS altyapısının kaynaklarını korumak içindir.
Ian Robertson

Yanıtlar:


552

EF bağlantı dizesinde varsayılan komut zaman aşımı süresini belirten bilinen bir hata var.

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

Bağlantı dizesinden değeri kaldırın ve veri içeriği nesnesinin kendisine ayarlayın. Bağlantı dizesinden çakışan değeri kaldırırsanız bu çalışır.

Varlık çerçeve çekirdek 1.0:

this.context.Database.SetCommandTimeout(180);

Varlık Çerçevesi 6:

this.context.Database.CommandTimeout = 180;

Varlık Çerçevesi 5:

((IObjectContextAdapter)this.context).ObjectContext.CommandTimeout = 180;

Entity Framework 4 ve altı:

this.context.CommandTimeout = 180;

5
Edmx kullanarak bunu nasıl başarabilirim?
02:50

2
EntityFramework uygulamasının hangi sürümünde bu düzeltildi? Bunun için EF hatasını bulamıyorum.
rudimenter

7
Bunun bir hata olduğuna inanmıyorum, daha ziyade tasarım gereği, buradaki Açıklamalar bölümüne bakın link
Mick P

3
Bazı ayarlar ms ve s kimi, ben baktım Çünkü burada , CommandTimeout saniye içindedir.
JabberwockyDecompiler

6
Entity Framework 7'de bunu DbContext / IdentityDbContext yapıcısında ayarlayabilirsiniz:this.Database.SetCommandTimeout(180);
Thomas Hagström

101

Bir DbContext kullanıyorsanız, komut zaman aşımını ayarlamak için aşağıdaki yapıcıyı kullanın:

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

3
@ErickPetru, bu yüzden kolayca dakikalar farklı bir sayıya değiştirebilirsiniz :), ayrıca derleyici bu çarpımı optimize eğer ben çok şaşırmazdım!
Joel Verhagen

2
@JoelVerhagen, şaşırmayın. Otomatik optimizasyonun ne zaman gerçekleştiğine ilişkin iyi bir açıklama: stackoverflow.com/questions/160848/… . Bu durumda, (iki değişmez değer olduğu için) bile olduğunu varsayalım, ama dürüstçe kodun bu şekilde garip olduğunu düşünüyorum.
Erick Petrucelli

33
meh ... çocuklar açlıktan ölüyor ... 1 * 60'ı kimin umurunda?
Timmerz

9
@ErikPetru, bu aslında çok yaygın bir uygulamadır ve kodu daha okunabilir hale getirir.
Calvin

DbContextTüretilmiş sınıfımın bir edmxdosyadan otomatik olarak oluşturulduğu göz önüne alındığında, bunu işlemenin en iyi yolu nedir ?
Matt Burland

41

DbContextVe EF v6 + kullanıyorsanız alternatif olarak şunları kullanabilirsiniz:

this.context.Database.CommandTimeout = 180;

13

Genellikle bir işlem içindeki işlemlerimi gerçekleştiririm . Deneyimlediğim gibi, bağlam komutu zaman aşımını ayarlamak yeterli değildir, ancak işlemin bir zaman aşımı parametresi olan bir yapıcıya ihtiyacı vardır. Düzgün çalışması için her iki zaman aşımı değerini ayarlamak zorunda kaldı.

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

İşlevin sonunda komut zaman aşımı süresini önceki değerde bir önceki değere geri ayarladım.

EF6'yı kullanma


Hiç de iyi bir yaklaşım değil. Çok fazla işlem kapsamı eklerdim ve bir projede bana kabus oldu. Sonunda tüm işlem kapsamını EF 6+ içinde tek bir SAVEChanges () ile değiştirdi. Bu coderwall.com/p/jnniww/…
Aylar

Bu cevabın daha yüksek oyu olmalı. Zaman aşımını artırmak için tüm farklı yolları denedim, ancak sadece BOTH bağlam komutu zaman aşımı ve İşlem kapsamını ayarladığımda işe yaradı.
Gang

3

Bu çok eski iş parçacığı çalışan biliyorum, ama yine de EF bu sorunu çözmedi. Otomatik oluşturulan DbContextkullanıcıları zaman aşımını manuel olarak ayarlamak için aşağıdaki kodu kullanabilir.

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;
    }

3

Entity Framework'ü benim gibi kullanıyorsanız Startup sınıfında zaman aşımı'nı aşağıdaki gibi tanımlamanız gerekir:

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

1

Ben bunu finanse ediyorum. Belki birine yardım eder:

İşte başlıyoruz:

EF ile LINQ kullanıyorsanız, listede yer alan bazı unsurları bu şekilde ararsanız:

await context.MyObject1.Include("MyObject2").Where(t => IdList.Contains(t.MyObjectId)).ToListAsync();

IdList'te birden fazla Kimlik bulunana kadar her şey yolunda gidiyor.

Listede yalnızca bir Kimlik varsa “zaman aşımı” sorunu ortaya çıkar. Sorunu çözmek için IdList'teki kimlik sayısını kontrol etmek için if koşulunu kullanın.

Misal:

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();
}

Açıklama:

Sql Profiler'ı kullanmayı deneyin ve Varlık frameeork tarafından oluşturulan Select deyimini kontrol edin. ...

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.