2012-06-21 27 views
3

HttpClient調用ASP.NET Web API方法調用EF存儲庫的方案。 我在捕獲SQL異常時遇到了問題。如何處理IQueryable <>方法中的後端異常?

客戶:

try 
{ 
    var client = new HttpClient(); 
    var httpRequestMessage = new HttpRequestMessage(); 
    var response = await client.SendAsync(httpRequestmessage); 
    response.EnsureSuccessStatusCode(); 
} 
catch (Exception ex) 
{ 
    // internal error 500 here 
} 

的Web API:

[HttpGet] 
public IQueryable<Data> GetData() 
{ 
    try 
    { 
    return repository.Data(); 
    } 
    catch (Exception ex) 
    { 
    // Nothing here 
    } 
} 

庫:

public IQueryable<Data> GetData() 
{ 
    try 
    { 
    return dbContext.Data.Where(d=>d.Id == 1) 
    } 
    catch (Exception ex) 
    { 
    // nothing here 
    } 
} 

我如何處理SQL服務器例外(如連接問題)? API層和存儲庫層都不會捕獲它們。 如果我想轉成可查詢資料庫中的數組:

var arr = dbContext.Data.Where(d => d.Id == 1).ToArray(); 

這當然會被抓到。但是這個可查詢的情況怎麼樣,我怎麼能抓住這些?

+0

我假設你在客戶端得到一個'WebException'。從「WebException」獲取響應並分析獲得OData XML錯誤可能是可能的。 –

回答

1

你無法處理任何異常的原因是IQueryable通常有一個懶惰的實現。除非你試圖通過它們來枚舉,否則什麼都不會發生。如果您想要捕捉的是查詢評估異常,則可以通過繼承QueryableAttribute來使用簡單的技巧。代碼如下,

public class QueryableWithExceptionAttribute : QueryableAttribute 
{ 
    public override IQueryable ApplyQuery(IQueryable queryable, ODataQueryOptions queryOptions) 
    { 
     IQueryable result = base.ApplyQuery(queryable, queryOptions); 
     try 
     { 
      result.GetEnumerator(); // eager evaluate to catch exceptions 
     } 
     catch(Exception) 
     { 
      // do stuff 
     } 

     return result; 
    } 
} 

這將執行在服務器上的查詢,我也會得到一些結果。它仍然具有不捕獲整個結果集的優點/缺點,這意味着如果您有一個較大的結果集,並且初始獲取後存在連接問題,則無法捕獲這些異常。儘管如此,小結果集應該足夠好。如果你想要一個更強大的解決方案,你可以這樣做對整個結果集加載到內存中,而不是result = LoadIntoMemory(result);result.GetEnumerator();

public static IQueryable LoadIntoMemory(IQueryable q) 
    { 
     MethodInfo mi = typeof(QueryableWithExceptionAttribute).GetMethod("LoadIntoMemoryInternal", BindingFlags.NonPublic | BindingFlags.Static); 
     return mi.MakeGenericMethod(q.ElementType).Invoke(null, new[] { q }) as IQueryable; 
    } 

    private static IQueryable<T> LoadIntoMemoryInternal<T>(IQueryable<T> q) 
    { 
     return q.ToList().AsQueryable(); 
    } 

這當然有可能使用更多的內存的缺點。

相關問題