2016-04-12 9 views
0

Ich habe sehr grundlegende grundlegende Zweifel in Bezug auf asynchrone Web API-Programmierung. Ich möchte SaveCaseSearch in meinem Controller asynchron aufrufen. Aber der Anruf durchläuft verschiedene Ebenen von DAL und ruft schließlich DB auf.Asynchrone Controller in Web Api

Sollen diese aufeinander folgenden Aufrufe auch asynchron erfolgen?

Ich bin sehr neu in der Welt der Async, so dass ich vielleicht schon einige Fehler gemacht habe. Korrigiere mich einfach, wenn etwas nicht stimmt.

Also für den Controller, mache ich so etwas wie die folgende Liste:

/*Create API for Case*/ 
[HttpPost] 
[Route("createcase")] 
public IHttpActionResult PostCreateCase([FromBody] ARC.Donor.Business.Case.CreateCaseInput CreateCaseInput) 
{ 
    ARC.Donor.Service.Case.CaseServices cs = new ARC.Donor.Service.Case.CaseServices(); 
    var searchResults = cs.createCase(CreateCaseInput); 
    List<CreateCaseOutput> searchOutputResults = (List<CreateCaseOutput>)searchResults; 
    if (!string.IsNullOrEmpty(searchOutputResults.ElementAt(0).o_case_seq.ToString())) 
     SaveCaseSearchDetails(SaveSearchInput); /*This should be called asynchronously*/ 
    return Ok(searchResults); 
} 

Diese

SaveCaseSearchDetails

muss nun in Asynchron-Modus aufgerufen werden. So habe ich geschrieben:

[HttpPost] 
public async Task<IHttpActionResult> SaveCaseSearchDetails([FromBody] ARC.Donor.Business.SaveSearchInput SaveSearchInput) 
{ 
    ARC.Donor.Service.Case.CaseServices cs = new ARC.Donor.Service.Case.CaseServices(); 
    var searchResults = await cs.saveCaseSearchDetails(SaveSearchInput); 
} 

Dann, wenn das richtig ist

sollten die aufeinander folgenden Anrufe async sein?

Denn jetzt sind sie

public IList<Entities.Case.SaveCaseSearchOutput> saveCaseSearch(ARC.Donor.Data.Entities.Case.SaveCaseSearchInput SaveCaseSearchInput) 
{ 
    Repository rep = new Repository(); 
    string strSPQuery = string.Empty; 
    List<object> listParam = new List<object>(); 
    SQL.CaseSQL.getCreateCaseParameters(SaveCaseSearchInput, out strSPQuery, out listParam); 
    var AcctLst = rep.ExecuteStoredProcedure<Entities.Case.SaveCaseSearchOutput>(strSPQuery, listParam).ToList(); 
    return AcctLst; 
} 

Ist

SQL.CaseSQL.getCreateCaseParameters

Methode in asynchroner Weise aufgerufen werden muss? Aber in diesem Fall die sofortige nächste Zeile

rep.ExecuteStoredProcedure

erfolgreich Recht nicht ausführen kann? Weil strSPQuery von der vorherigen Zeile selbst kommt?

Ich denke falsch? Bitte korrigieren Sie mich.

+1

'Sollten diese aufeinanderfolgenden Anrufe auch asynchron durchgeführt werden?' Ja, wenn Sie "wahre" Async-Funktionalität wollen. –

+0

Aber in diesem Fall, wie im letzten Fall habe ich dargestellt, wird es richtig brechen? – StrugglingCoder

+0

Was erwarten Sie von "asynchron"? Wenn die blockierenden Operationen * selbst * nicht asynchron sind, müssen Sie immer noch einen Thread blockieren, um sie auszuführen. –

Antwort

1

Sie können SQL.CaseSQL.getCreateCaseParameters nicht asynchron (mit Warten) aufrufen, da das Schlüsselwort out verwendet wird, das für asynchrone Metoden nicht verfügbar ist.

Wenn Sie möchten, dass Ihr DB-Aufruf asynchron erfolgt, müssen Sie eine DB-Methode finden, die Sie await können. Dann können Sie die Methode saveCaseSearch so ändern, dass sie auch asynchron ist und Sie von Ihrer Controller-Methode erwarten.

+0

Momentan möchte ich meine bestehenden Service- und DAL-Layer-Funktionalitäten nicht unterbrechen. Kann ich sie also synchron halten? Oder ist es gegen asynchrone Topologie und wird Leistungsproblem in meiner Anwendung verursachen? – StrugglingCoder

+0

Wenn eine asynchrone Methode kein "Warten" enthält, wird sie synchron ausgeführt, sodass nichts Unerwartetes passieren sollte. Ihre IDE warnt Sie möglicherweise, aber das ist es. (Beachten Sie, dass es in diesem Fall sinnlos ist, Ihre Controller-Methode asynchron zu machen, und Sie können sie auch synchron machen) – GWigWam

+2

@StrugglingCoder Wenn Sie async wollen, müssen * Sie * Ihre synchrone DAL unterbrechen und * asynchrone * Methoden hinzufügen, die am Ende stehen * real * asynchrone Datenbankaufrufe, zB Aufruf von ExecuteReaderAsync anstelle von ExecuteReader. Sonst blockierst du einen Thread - entweder das Original oder ein anderes, mit dem du Task.Run beginnst. Sie werden keine der Vorteile bekommen, aber Sie zahlen einen zusätzlichen Overhead –

5

Sollen diese aufeinander folgenden Aufrufe auch asynchron erfolgen?

Ja.

SaveCaseSearchDetails muss nun in asynchronem Modus

Das ist die harte Art und Weise, es zu tun genannt werden.

Ein viel natürlicher Ansatz ist es, bei anderen Ende zu starten. Welcher Teil Ihres Codes tatsächlich die Datenbankabfrage ausführt, sollte asynchron first erfolgen. Dann rufen Sie es mit await, die diese Methoden async macht, so sollten sie mit await, etc. aufgerufen werden, bis Sie endlich Ihre Controller-Aktion erreichen, die die letzte Sache asynchron gemacht werden soll.

tatsächlich das Problem, das ich bin vor ist SaveCaseSearchDetails (SaveSearchInput) in PostCaseCreate Methode aufgerufen werden muss etwas Asynchron, weil wir nicht wollen, warten Rückkehr Ok (search)

Ah, das ist ein ganz andere Frage. Sie möchten zurückkehren früh. Async wird Ihnen nicht dabei helfen; wie ich auf meinem Blog (und in einer MSDN article on async ASP.NET), async does not change the HTTP protocol erklären.

Es gibt ein paar Ansätze zu returning early or "fire and forget" on ASP.NET, die ich auf meinem Blog beschreibe. Allerdings wurde ASP.NET nicht für dieses Szenario entwickelt, so dass Sie vorsichtig vorgehen müssen. Die einzige vollständig zuverlässige Lösung ist eine ordnungsgemäß verteilte Architektur.

+0

Danke für die Einsicht. Aber SQL.CaseSQL.getCreateCaseParameters (SaveCaseSearchInput, out strSPQuery, out listParam); var AcctLst = rep.ExecuteStoredProcedure (strSPQuery, listParam) .ToList(); die erste Zeile enthält out-Schlüsselwort, das nicht von erwartet wird, nehme ich an. Und die unmittelbare Zeile verwendet das out-Keyword-Ergebnis. Wie erreiche ich das mit Async/Abwarten? – StrugglingCoder

+1

@StrugglingCoder: Sie nähern sich immer noch aus der falschen Richtung. Wenn 'getCreateCaseParameters' nicht mit der db (was wahrscheinlich ist) spricht, dann müssen Sie es nie 'async' machen. Wenn dies der Fall ist, müssen Sie nur zwei Werte zurückgeben. –

Verwandte Themen