我有一个类:
class SampleRepositoryClass
{
void MethodA()
{
try
{
//do something
}
catch(Exception ex)
{
LogError(ex);
throw ex;
}
}
void MethodB(int a, int b)
{
try
{
//do something
}
catch(Exception ex)
{
LogError(ex);
throw ex;
}
}
List<int> MethodC(int userId)
{
try
{
//do something
}
catch(Exception ex)
{
LogError(ex);
throw ex;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,您可以看到在每个方法(MethodA,MethodB,MethodC)中都有try ... catch块来记录错误,然后抛出更高级别.
想象一下,当我的Repository类可能有超过一百个方法时,在每个方法中我都尝试了... catch块,即使只有一行代码.
现在,我的目的是减少这些重复的异常日志记录代码,并在类级而不是方法级别记录所有异常.
我的大部分功能都涉及检查某些内容是否存在。如果没有,我返回 HttpNotFound()。它们还涉及检查参数是否正确。如果不是,我返回 HttpBadRequest()。如果一切正常,我通常会返回 OK(dataGoesHere)。
但是,当使用 Try Catch 块并抛出错误时我应该做什么。在 Catch 中,我想简单地返回存在服务器错误。我见过一些 API 实际上也返回自定义消息。
看起来 ASP.NET 5 中的事情有很大不同。我无法像 Web api 2 中那样返回 BadRequest()、Conflict() 等。
我认为CancellationToken在控制器中像这样使用将是一个好主意:
[HttpGet("things", Name = "GetSomething")]
public async Task<ActionResult> GetSomethingAsync(CancellationToken ct) {
var result = await someSvc.LoadSomethingAsync(ct);
return Ok(result);
}
Run Code Online (Sandbox Code Playgroud)
问题是,现在Azure Application Insights显示了许多类型的异常System.Threading.Tasks.TaskCancelledException: A Task was canceled.以及偶然的异常Npgsql.PostgresException: 57014: canceling statement due to user request。这是我不需要的噪音。
使用标准方法-将Application Insights注册为服务services.AddApplicationInsightsTelemetry(Configuration);。
我以为我可以进入应用程序管道并捕获上述异常,将它们转换为正常的响应。我将代码放在各个地方。它捕获任何异常,如果IsCancellationRequested,则返回一个虚拟响应。否则,它将抛出捕获的异常。
app.Use(async (ctx, next) =>
{
try { await next(); }
catch (Exception ex)
{
if (ctx.RequestAborted.IsCancellationRequested)
{
ctx.Response.StatusCode = StatusCodes.Status418ImATeapot;
}
else { throw; }
}
});
Run Code Online (Sandbox Code Playgroud)
该代码的工作方式是更改响应。但是,异常仍会发送到Application Insights。
RequestAborted.IsCancellationRequested可以尝试捕获特定的异常。原因是,如果我已经发现一个实现抛出了一种并非源自OperationCanceledException …c# cancellation-token azure-application-insights asp.net-core
我惊呆了。我一直认为throw在 catch 块中本身会抛出手头的异常而不改变堆栈跟踪,但throw ex在 catch 块中会更改堆栈跟踪以显示源自语句位置的异常。
采取以下两个代码块。我希望输出会略有不同,因为一个使用throw而另一个使用throw ex,但两者之间的输出是相同的,并且在两种情况下引发初始异常的实际源代码行都丢失了,这对我来说似乎很糟糕。我缺少什么?
第一个示例的行为符合我的预期:
using System;
public class Program
{
public static void Main()
{
try
{
DummyWork();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
private static void DummyWork()
{
try
{
throw new Exception("dummy");
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw ex; // I would expect to lose the information about the inciting line 5 above this one in this case.... and I do.
} …Run Code Online (Sandbox Code Playgroud) 使用之间有什么区别
catch(Exception ex)
{
...
throw ex;
}
Run Code Online (Sandbox Code Playgroud)
和使用
catch // might include (Exception)
{
...
throw;
}
Run Code Online (Sandbox Code Playgroud) 我正在处理一个应用程序一切正常,但我得到例外
枚举尚未启动或已完成.
这是我生成此异常的代码.
for (int i = 0; i < SelectedItems.Count; i++)
{
lineDS = new DataSet();
datDs = new DataSet();
datDs = DatelineData(SelectedItems[i].ToString(), Starttime, Endtime, NUDTextBox, txtSensorLess, dtpStartDate, dtpEndDate);
lineDS =GraphlineDraw(SelectedItems[i].ToString(),Starttime,Endtime,NUDTextBox,txtSensorLess,dtpStartDate,dtpEndDate);
if (datDs.Tables[0].Rows.Count > 0 & lineDS.Tables[0].Rows.Count > 0)
{
var dates = (from dr in datDs.Tables[0].AsEnumerable()
select new
{
date = dr.Field<DateTime>("DateRecorded"),
}.date).ToList();
var Rate = (from dr in lineDS.Tables[0].AsEnumerable()
select new
{
rate = dr.Field<double>(SelectedItems[i])
}.rate).ToList();
var datesDataSource = new EnumerableDataSource<DateTime>(dates);
datesDataSource.SetXMapping(x => dateAxis.ConvertToDouble(x));
var RateDataSource = …Run Code Online (Sandbox Code Playgroud) ReSharper建议重新抛出异常然后,当我这样做时,它表示整个catch子句无论如何都是多余的,并建议将其删除.
我(从MethodMan使用此代码在这里):
public static DataTable ExecuteDataSet(string sql, CommandType cmdType, params SqlParameter[] parameters)
{
using (DataSet ds = new DataSet())
using (SqlConnection connStr = new SqlConnection(UsageRptConstsAndUtils.CPSConnStr))
using (SqlCommand cmd = new SqlCommand(sql, connStr))
{
cmd.CommandType = cmdType;
foreach (var item in parameters)
{
cmd.Parameters.Add(item);
}
try
{
cmd.Connection.Open();
new SqlDataAdapter(cmd).Fill(ds);
}
catch (SqlException ex)
{
throw;
}
return ds.Tables[0];
}
}
Run Code Online (Sandbox Code Playgroud)
当我在解决方案中有ReSharper Inspect> Code Issues时,它想知道"异常重新抛出可能是否有意":
catch (SqlException ex)
{
throw ex;
}
Run Code Online (Sandbox Code Playgroud)
如果我接受ReSharper的建议修复("rethrow exception"),Resharper将删除"ex":
catch (SqlException ex)
{
throw; …Run Code Online (Sandbox Code Playgroud) 昨天找到的东西让我意识到我很可能仍然缺少关于C#的基本花絮.
我有一个无状态服务结构应用程序.我在主循环中有一个尝试捕获.如果我在这个循环中抛出一个异常,它会跳出while循环并且服务有效地停止.如果我throw向catch子句添加一个,则服务将重新启动.
protected override async Task RunAsync(CancellationToken cancellationToken)
{
try
{
long iterations = 0;
while (true)
{
cancellationToken.ThrowIfCancellationRequested();
await Task.Delay(TimeSpan.FromSeconds(3), cancellationToken).ConfigureAwait(false);
// Do stuff...
if (iterations > 4) {
throw new Exception();
}
ServiceEventSource.Current.ServiceMessage(this.Context, $"Working-{++iterations}");
}
}
catch (Exception ex)
{
// Log stuff...
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
有人可以解释为什么这是或指示我到哪里可以得到答案?我找不到任何可以解释这种行为的东西.
编辑:这不是重复是什么"投掷"和"投掷前"之间有什么区别?因为,据我所见,它没有解释我的问题,为什么函数再次运行.该主题更多的是解释之间的区别throw和throw new各自的堆栈跟踪.
在throw;和之间选择的最佳做法是throw ex;什么?有没有?关于 - 例如 - 这个简单的片段:
try{
// some code
} catch (Exception ex) {
// some catcher code
// throw; ?
// or
// throw ex; ?
// how to decide which one?
}
Run Code Online (Sandbox Code Playgroud)
更新: 我知道上面的两个区别.问题是如何决定使用其中之一?有没有最好的做法来做出更好的选择?
我试图理解throw和throw ex之间的区别。为了帮助我的学习,我对理论进行了一些研究,将我带到以下链接:
总结以上几点,区别是:
throw重新引发捕获的异常,并保留堆栈跟踪。throw ex引发相同的异常,但是将堆栈跟踪重置为该方法。
因此,我继续为同一个应用程序创建了一个演示应用程序,以了解操作上的差异。
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Calc c = new Calc();
c.Test();
}
}
class Calc
{
public void Test()
{
try
{
int a = 10;
int b = 10;
int c = 10 / (a - b);
}
catch (Exception ex)
{
throw; //throw statement
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这给我的输出为:-
未处理的异常:System.DivideByZeroException:试图除以零。在C:\ kgn \ personal \ workspace \ ConsoleApplication1 \ ConsoleApplication1 …
好吧我是T-SQL的新手,我正在努力让我的插入方法起作用.我得到的错误是我的insert方法的未知构造函数.我不知道为什么我有错误,我相信我确定没有正确引用.先谢谢你!
SqlConnection dbConn = null;
LabelData LadelList = new LabelData();
try
{
using (dbConn = new SqlConnection(Properties.Settings.Default["connectionname"].ToString()))
LabelData addNewVersion = new LabelData(@"INSERT INTO PackLabelVersion (VersionID, VersionNumber, FormatID) VALUES (@VersionID, @VersionNumber, @FormatID)", dbConn);
addNewVersion.Parameters.AddWithValue("@VersionID", VersionID);
addNewVersion.Parameters.AddWithValue("@VersionNumber", VersionNumber);
addNewVersion.Parameters.AddWithValue("@Quantity", FormatID);
dbConn.Open();
addNewVersion.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ex;
}
Run Code Online (Sandbox Code Playgroud) 我正在编写一个检查输出是否为函数的函数,DBNull如果泛型类型可以为null则返回null.如果不是,它只是抛出错误.
更新:添加了所有建议
public T Get<T>(string key)
{
int ordinal = reader.GetOrdinal(key);
if (reader.IsDBNull(ordinal))
{
if (typeof(T).GetTypeInfo().IsValueType && Nullable.GetUnderlyingType(typeof(T)) == null) // isn't a nullable field
throw new InvalidCastException();
else return default(T);
}
return reader.GetFieldValue<T>(ordinal);
}
Run Code Online (Sandbox Code Playgroud)
但是我不确定是否default(T)为每个可空字段返回null.如果现在有任何其他方法使它返回null?