2011-09-03 25 views
9
WCF oturumu koruyacak bir hizmet oluşturmak için gereken

bir yıkıcı çağrıldığında. DB'den veri okuduğum kurucuda ve oturum sona erdiğinde onu geri kaydetmek zorundayım. Ben (Müvekkilim ServiceClient SvcUtil.exe ile oluşturuldu) Client üzerinde() Kapat çağırdığınızda bir WCF hizmeti

anlıyorum Eğer

doğru oturumu sona erer. Bunu sınamak

Ben bazen sonra yaklaşık olarak adlandırılır görüyoruz. 10 dakika, bazen 20 dakika sonra ve bazen hiç de değil.

ne zaman yıkıcı denir?

Servis

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] 
    public class Service:IService 
    { 
    private User m_User = null; 

    public Service() 
    { 
     m_User = User.LoadFromDB(); 
    } 

    ~Service() 
    { 
     m_User.SaveToDB(); 
    } 

    public void SetName(string p_Name) 
    { 
     m_User.Name = p_Name; 
    } 
    } 

Web.config

<?xml version="1.0"?> 
<configuration> 
    <system.web> 
    <sessionState timeout="2" /> 
    </system.web> 
    <system.serviceModel> 
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" /> 
     <services> 
     <service name="Karatasi.Services.B2C" behaviorConfiguration="ServiceBehavior"> 
      <host> 
      <baseAddresses> 
       <add baseAddress="http://localhost:19401/B2C.svc"/> 
      </baseAddresses> 
      </host> 
     <endpoint 
      address="" 
      binding="wsHttpBinding" 
      bindingConfiguration="test" 
      contract="Karatasi.Services.IB2C" 
     /> 
     <endpoint 
      address="mex" 
      binding="mexHttpBinding" 
      contract="IMetadataExchange" 
     /> 
     </service> 
    </services> 
    <bindings> 
    <wsHttpBinding> 
     <binding name="test" receiveTimeout="00:01:00" > 
     <reliableSession enabled="true" ordered="false" inactivityTimeout="00:01:00"/> 
     </binding> 
    </wsHttpBinding> 
    </bindings> 
    <behaviors> 
    <serviceBehaviors> 
     <behavior name="ServiceBehavior"> 
     <serviceMetadata httpGetEnabled="true" /> 
     <serviceDebug includeExceptionDetailInFaults="false" /> 
     </behavior> 
    </serviceBehaviors> 
    </behaviors> 
</system.serviceModel> 
</configuration> 

Müşteri

ServiceClient serviceClient = null; 
    try 
    { 
     serviceClient = new ServiceClient(); 
     serviceClient.SetName("NewName"); 
     Console.WriteLine("Name set"); 
    } 
    catch (Exception p_Exc) 
    { 
     Console.WriteLine(p_Exc.Message); 
    } 
    finally 
    { 
     if (serviceClient != null) 
     { 
     if (serviceClient.State == CommunicationState.Faulted) 
     { 
      serviceClient.Abort(); 
     } 
     else 
     { 
      serviceClient.Close(); 
     } 
     } 
     Console.ReadKey(); 
    } 
+0

İlk tamamen yanlış servis tasarımdır kullanabilirsiniz. –

cevap

16

docs

pr itibaren ogrammer, yok edicinin olarak adlandırıldığı zaman üzerinde hiçbir kontrolü yoktur, çünkü bu çöp toplayıcı tarafından belirlenir. Çöp kutusu toplayıcı, artık uygulaması tarafından kullanılmayan nesneleri denetler. Yıkım için uygun bir nesneyi göz önünde bulundurursa, yıkıcıyı çağırır (varsa) ve nesnesini depolamak için kullanılan belleği geri alır. Program çıktığında yıkıcılar da denir.

Uygulamanızla ilgili bir sorun var. Verileri sürdürmek için destructor kullanıyorsunuz. Bu yanlıştır çünkü yıkıcılar deterministik olarak adlandırılamazlar, ayrı bir sonlandırma kuyruğunda işlenirler. Bu, nesneyi yok etmiş olsanız bile, yıkıcısına derhal çağrılmayacağınız anlamına gelir.

bu
yıkıcı çıkarın ve yerine ıdisposable deseni kullanmak nasıl giderilir?, Dispose içine mantığı kaydetmek koydu. oturumu sonlandırıldıktan sonra WCF da IDisposable.Dispose

public class Service:IService, IDisposable 
{ 
    public void Dispose() 
    { 
     //your save logic here 
    } 
} 

DÜZENLEME
Pls dediğimiz bu cevaba yorumunu görecek. Gerçekte, IDisposable'un veri tabanı taahhütleri için uygun bir yer olmadığını kabul ediyorum, daha önce bana gelmedi. Ayrıca açıklamada sağlanan çözümlere sende bunun explicit session demarcation

+16

Hayır! Onu 'IDisposable.Dispose' içine koymayın! 'IDisposable.Dispose' yönetilen kaynakları temizlemek içindir. Veritabanına kaydetmek, yönetilen bir kaynağı temizlemiyor. Bu, bu arabirimin * kabul edilen * ve * beklenen * kullanımına karşı gelir. Ya hale 'veritabanına değişiklikler kaydedilmeye veya hizmetin' Commit' başka yöntem sağlar SetName'. Ayrıca, küçük biblo, C# olarak biz buna "finalizer" diyoruz. Evet, bu konuda karışıklık var. – jason

İlgili konular