4

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
}

网络接口:

[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 Server 异常(例如连接问题)?API 层和存储库层都没有捕获它们。如果我将可查询转换为存储库中的数组:

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

那当然会被抓住。但是可查询的场景怎么样,我怎样才能抓住那些呢?

4

1 回答 1

2

您无法处理任何异常的原因是 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();
    }

当然,这有可能使用更多内存的缺点。

于 2013-03-10T06:06:55.083 回答