Exception handling 如何在IQueryable中处理后端异常<&燃气轮机;方法?

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

HttpClient调用ASP.NET Web API方法、调用EF存储库的场景。 我在捕获SQL异常时遇到问题

客户:

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