【发布时间】:2016-10-09 08:24:12
【问题描述】:
我整天都被这个问题所困扰,似乎无法在网上找到任何可以指出可能导致它的原因。
我在 Logger 类中有以下日志记录方法,以下代码调用记录器。当没有异常发生时,所有日志语句都可以正常工作,但是当异常发生时,日志语句根本不会运行(但是它们确实从 Web 服务调用中运行)。
Logger 记录方法:
public static Guid WriteToSLXLog(string ascendId, string masterDataId, string masterDataType, int? status,
string request, string requestRecieved, Exception ex, bool isError)
{
var connection = ConfigurationManager.ConnectionStrings["AscendConnectionString"];
string connectionString = "context connection=true";
// define INSERT query with parameters
var query =
"INSERT INTO " + AscendTable.SmartLogixLogDataTableName +
" (LogID, LogDate, AscendId, MasterDataId, MasterDataType, Status, Details, Request, RequestRecieved, StackTrace, IsError) " +
"VALUES (@LogID, @LogDate, @AscendId, @MasterDataId, @MasterDataType, @Status, @Details, @Request, @RequestRecieved, @StackTrace, @IsError)";
var logId = Guid.NewGuid();
using (var cn = new SqlConnection(connectionString))
{
if (!cn.State.Equals(ConnectionState.Open))
{
cn.Open();
}
// create command
using (var cmd = new SqlCommand(query, cn))
{
try
{
// define parameters and their values
cmd.Parameters.Add("@LogID", SqlDbType.UniqueIdentifier).Value = logId;
cmd.Parameters.Add("@LogDate", SqlDbType.DateTime).Value = DateTime.Now;
if (ascendId != null)
{
cmd.Parameters.Add("@AscendId", SqlDbType.VarChar, 24).Value = ascendId;
}
else
{
cmd.Parameters.Add("@AscendId", SqlDbType.VarChar, 24).Value = DBNull.Value;
}
cmd.Parameters.Add("@MasterDataId", SqlDbType.VarChar, 50).Value = masterDataId;
cmd.Parameters.Add("@MasterDataType", SqlDbType.VarChar, 50).Value = masterDataType;
if (ex == null)
{
cmd.Parameters.Add("@Status", SqlDbType.VarChar, 50).Value = status.ToString();
}
else
{
cmd.Parameters.Add("@Status", SqlDbType.VarChar, 50).Value = "2";
}
if (ex != null)
{
cmd.Parameters.Add("@Details", SqlDbType.VarChar, -1).Value = ex.Message;
if (ex.StackTrace != null)
{
cmd.Parameters.Add("@StackTrace", SqlDbType.VarChar, -1).Value =
ex.StackTrace;
}
else
{
cmd.Parameters.Add("@StackTrace", SqlDbType.VarChar, -1).Value = DBNull.Value;
}
}
else
{
cmd.Parameters.Add("@Details", SqlDbType.VarChar, -1).Value = "Success";
cmd.Parameters.Add("@StackTrace", SqlDbType.VarChar, -1).Value = DBNull.Value;
}
if (!string.IsNullOrEmpty(request))
{
cmd.Parameters.Add("@Request", SqlDbType.VarChar, -1).Value = request;
}
else
{
cmd.Parameters.Add("@Request", SqlDbType.VarChar, -1).Value = DBNull.Value;
}
if (!string.IsNullOrEmpty(requestRecieved))
{
cmd.Parameters.Add("@RequestRecieved", SqlDbType.VarChar, -1).Value = requestRecieved;
}
else
{
cmd.Parameters.Add("@RequestRecieved", SqlDbType.VarChar, -1).Value = DBNull.Value;
}
if (isError)
{
cmd.Parameters.Add("@IsError", SqlDbType.Bit).Value = 1;
}
else
{
cmd.Parameters.Add("@IsError", SqlDbType.Bit).Value = 0;
}
// open connection, execute INSERT, close connection
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
// Do not want to throw an error if something goes wrong logging
}
}
}
return logId;
}
发生日志记录问题的我的方法:
public static void CallInsertTruckService(string id, string code, string vinNumber, string licPlateNo)
{
Logger.WriteToSLXLog(id, code, MasterDataType.TruckType, 4, "1", "", null, false);
try
{
var truckList = new TruckList();
var truck = new Truck();
truck.TruckId = code;
if (!string.IsNullOrEmpty(vinNumber))
{
truck.VIN = vinNumber;
}
else
{
truck.VIN = "";
}
if (!string.IsNullOrEmpty(licPlateNo))
{
truck.Tag = licPlateNo;
}
else
{
truck.Tag = "";
}
if (!string.IsNullOrEmpty(code))
{
truck.BackOfficeTruckId = code;
}
truckList.Add(truck);
Logger.WriteToSLXLog(id, code, MasterDataType.TruckType, 4, "2", "", null, false);
if (truckList.Any())
{
// Call SLX web service
using (var client = new WebClient())
{
var uri = SmartLogixConstants.LocalSmartLogixIntUrl;
uri += "SmartLogixApi/PushTruck";
client.Headers.Clear();
client.Headers.Add("content-type", "application/json");
client.Headers.Add("FirestreamSecretToken", SmartLogixConstants.FirestreamSecretToken);
var serialisedData = JsonConvert.SerializeObject(truckList, new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Serialize
});
// HTTP POST
var response = client.UploadString(uri, serialisedData);
var result = JsonConvert.DeserializeObject<SmartLogixResponse>(response);
Logger.WriteToSLXLog(id, code, MasterDataType.TruckType, 4, "3", "", null, false);
if (result == null || result.ResponseStatus != 1)
{
// Something went wrong
throw new ApplicationException("Error in SLX");
}
Logger.WriteToSLXLog(id, code, MasterDataType.TruckType, result.ResponseStatus, serialisedData,
null, null, false);
}
}
}
catch (Exception ex)
{
Logger.WriteToSLXLog(id, code, MasterDataType.TruckType, 4, "4", "", null, false);
throw;
}
finally
{
Logger.WriteToSLXLog(id, code, MasterDataType.TruckType, 4, "5", "", null, false);
}
}
如您所见,我在整个方法中添加了几个日志语句。如果没有抛出异常,所有这些日志语句除了在 catch 块中的语句都是成功的。如果抛出异常,那么它们都不会成功。对于他们中的大多数人来说,无论是否存在异常,值都是完全相同的,所以我知道传递的值不是问题。我在想一些奇怪的事情正在发生,导致回滚或其他事情,但我没有在这里使用事务或任何东西。最后一件事是这个 DLL 正在通过 SQL CLR 运行,这就是我使用“context connection=true”作为连接字符串的原因。
提前致谢。
编辑:
我尝试将以下内容添加为我的连接字符串,但在尝试打开连接时出现异常,现在显示“另一个会话正在使用事务上下文”。我认为这与我通过触发器调用此 SQL CLR 过程有关。我试过的连接字符串是
connectionString = "Trusted_Connection=true;Data Source=(local)\\AARONSQLSERVER;Initial Catalog=Demo409;Integrated Security=True;";
这里也是触发器:
CREATE TRIGGER [dbo].[PushToSLXOnVehicleInsert]
ON [dbo].[Vehicle] AFTER INSERT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @returnValue int
DECLARE @newLastModifiedDate datetime = null
DECLARE @currentId bigint = null
DECLARE @counter int = 0;
DECLARE @maxCounter int
DECLARE @currentCode varchar(24) = null
DECLARE @currentVinNumber varchar(24)
DECLARE @currentLicPlateNo varchar(30)
declare @tmp table
(
id int not null
primary key(id)
)
insert @tmp
select VehicleID from INSERTED
SELECT @maxCounter = Count(*) FROM INSERTED GROUP BY VehicleID
BEGIN TRY
WHILE (@counter < @maxCounter)
BEGIN
select top 1 @currentId = id from @tmp
SELECT @currentCode = Code, @currentVinNumber = VINNumber, @currentLicPlateNo = LicPlateNo FROM INSERTED WHERE INSERTED.VehicleID = @currentId
if (@currentId is not null)
BEGIN
EXEC dbo.SLX_CallInsertTruckService
@id = @currentId,
@code = @currentCode,
@vinNumber = @currentVinNumber,
@licPlateNo = @currentLicPlateNo
END
delete from @tmp where id = @currentId
set @counter = @counter + 1;
END
END TRY
BEGIN CATCH
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
SELECT
@ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
IF (@ErrorMessage like '%Error in SLX%')
BEGIN
SET @ErrorMessage = 'Error in SLX. Please contact SLX for more information.'
END
RAISERROR (@ErrorMessage, -- Message text.
@ErrorSeverity, -- Severity.
@ErrorState -- State.
);
END CATCH;
END
GO
【问题讨论】:
-
"如果抛出异常,那么它们都不会成功。" 异常发生在哪里?您确定在这种情况下会调用此代码吗?我假设这段代码是一个存储过程,那么你能提供一个如何调用它的例子吗?
-
它实际上只是一个直接插入语句。异常可以是任何异常,但我正在测试的特定异常是我自己抛出的异常,即 SLX 中的应用程序异常错误。
-
我已经包含了根据我从 Web 服务收到的响应引发该异常的代码。
-
单步进入此代码并告诉我们发生异常的确切行。
-
抛出新的 ApplicationException("SLX 中的错误");
标签: c# sql-server exception-handling triggers sqlclr