Exception handling 如何在IQueryable中处理后端异常<&燃气轮机;方法?
HttpClient调用ASP.NET Web API方法、调用EF存储库的场景。 我在捕获SQL异常时遇到问题 客户:Exception handling 如何在IQueryable中处理后端异常<&燃气轮机;方法?,exception-handling,iqueryable,Exception Handling,Iqueryable,HttpClient调用ASP.NET Web API方法、调用EF存储库的场景。 我在捕获SQL异常时遇到问题 客户: try { var client = new HttpClient(); var httpRequestMessage = new HttpRequestMessage(); var response = await client.SendAsync(httpRequestmessage); response.EnsureSuccessStatusCode()
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
}
}
那当然会被抓住。但是关于可查询的场景,我如何捕获这些呢?您无法处理任何异常的原因是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()代码>
公共静态IQueryable装入内存(IQueryable q)
{
MethodInfo mi=typeof(QueryableWithExceptionAttribute).GetMethod(“装入内存内部”,BindingFlags.NonPublic | BindingFlags.Static);
返回mi.MakeGenericMethod(q.ElementType).Invoke(null,new[]{q})作为IQueryable;
}
专用静态IQueryable装入内存内部(IQueryable q)
{
返回q.ToList().AsQueryable();
}
当然,这样做的缺点是可能会占用更多内存。我假设您在客户端得到一个WebException
。可以从WebException
中提取响应并对其进行解析,以获得ODataXML错误。
var arr = dbContext.Data.Where(d => d.Id == 1).ToArray();
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;
}
}
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();
}