虚拟异常会停止执行子方法,但不会冒泡

时间:2018-09-26 18:16:51

标签: c# amazon-web-services .net-core aws-lambda

我有一个AWS lambda函数,该函数会响应SNS消息而执行。有一些莫名其妙的行为发生,子方法突然停止执行(好像引发了异常),但是父方法随后继续照常执行。

public void InsertEntity(Entity entity)
{
    _context.Entities.Add(entity);

    _logger.Log($"Before SaveChanges, entity.Id is {entity.Id}");

    _context.SaveChanges();

    _logger.Log($"After SaveChanges, entity.Id is {entity.Id}");

    if (entity.Id < 0)
        throw new Exception($"InsertEntity succeeded, but id is invalid: {entity.Id}");
}

public int? ImportEntity(string xml)
{
    var entity = new Entity(xml);

    _entityRepository.InsertEntity(entity);

    _logger.LogLine($"Entity inserted successfully with Id {entity.Id}");

    return entity.Id;
}

在这种情况下,上下文是使用PostgreSQL EF提供程序的标准DbContext。

首次创建实体时,Id为0。将其添加到上下文DbSet中时,id变为一个临时负整数,如-2147392341。调用SaveChanges后,应从数据库中为实体提供一个ID,一个正数。

这里的任何异常都应该冒泡到调用ImportEntity的方法上,并且应该处理错误。相反,我在AWS中的日志文件如下所示:

Before SaveChanges, entity.Id is -2147482647
Entity inserted successfully with Id -2147482647

并且在任何时候都不会引发异常的情况下返回负值。由于我在InsertEntity中有专门检查负值的代码,因此我唯一看到的可能性是SaveChanges引发了一个异常,该异常导致日志记录和否定检查都无法运行。但是父方法如何继续记录和执行并返回值?

我知道我的代码正在AWS上更新,因为我最近添加了“ SaveChanges”日志并显示了日志,并且同时添加了所有日志。

编辑

我直接在_context.SaveChanges();周围添加了try / catch并能够捕获潜在的异常。问题仍然存在,即使从ImportEntity内部抛出异常,为什么/如何继续执行InsertEntity函数。

编辑2

添加csproj定义:

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <AssemblyName>MyService</AssemblyName>
    <OutputType>Library</OutputType>
    <PackageId>MyService</PackageId>
    <GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
    <GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
    <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
    <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
    <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
    <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
    <GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
    <GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
</PropertyGroup>
<ItemGroup>
    <None Update="runtimes\linux\lib\netstandard1.3\System.Net.NetworkInformation.dll">
    <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    </None>
</ItemGroup>
<ItemGroup>
    <PackageReference Include="Amazon.Lambda.Core" Version="1.0.0" />
    <PackageReference Include="AWSSDK.S3" Version="3.3.16.2" />
    <PackageReference Include="Amazon.Lambda.Serialization.Json" Version="1.1.0" />
    <PackageReference Include="Amazon.Lambda.S3Events" Version="1.0.2" />
    <PackageReference Include="AWSSDK.XRay" Version="3.3.1.6" />
    <PackageReference Include="AWSXRayRecorder" Version="2.0.0-beta" />
    <PackageReference Include="AWSXRayRecorder.Handlers.AwsSdk" Version="2.0.0-beta" />
    <PackageReference Include="Castle.Core" Version="4.2.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="2.0.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0" />
    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="2.0.1" />
    <PackageReference Include="HtmlAgilityPack.NetCore" Version="1.5.0.1" />
    <PackageReference Include="Amazon.Lambda.SNSEvents" Version="1.0.0" />
    <PackageReference Include="System.Net.NetworkInformation" Version="4.3.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.0.1" />
    <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.0" />
    <PackageReference Include="AWSSDK.SimpleNotificationService" Version="3.3.0.24" />
</ItemGroup>
<ItemGroup>
    <DotNetCliToolReference Include="Amazon.Lambda.Tools" Version="2.1.0" />
</ItemGroup>
</Project>

以及AWS调用的顶级lambda方法,然后调用ImportEntity:

public void ProcessEntity(SNSEvent evnt, ILambdaContext context)
{
    var fileContent = GetFileContent(evnt);

    using (var lifetimeScope = Container.BeginLifetimeScope())
    {
        var processor = processingScope.Resolve<IEntityProcessor>();
        var result = processor.ImportEntity(fileContent);

        context.Logger.LogLine($"Successfully imported entity, Id is {result.Value}");
        return result;
    }
}

1 个答案:

答案 0 :(得分:4)

这个问题已经出现过很多次了。我怀疑根本原因与未等待的异步进程引发异常时发生的情况类似:它们不会冒泡到您的代码,因为它们并非旨在这样做。

在其他情况下,此类问题已解决,则根故障通常在代码外部,这意味着数据库连接,映射中的某个位置,甚至在数据库端本身。当发生这种情况时,线程将简单地死掉,并且执行将继续,就像SaveChanges已正常返回一样。

数据库超时可能会导致此行为。类似于POCO文件的文件与数据库不正确一样,也可能导致该文件,并且您可能不会收到警告。 32位和64位文件位置之间的混乱可能会导致这种情况。如果数据库是事务性的,脏的ObjectStateEntry对象无法持久保存,则任何事务失败都会导致这种情况。

我将从查看数据库中的错误日志开始-令人惊讶的是,这样做时问题频繁出现。如果日志未显示问题,则将工具放在数据库端,然后查看接收到的查询,查询结果和查询执行。那很可能会指出正确的方向。

如果这不能使您畅通无阻,则值得花时间进行完整且可执行的最小化复制并发布。这将为我提供寻找问题根源所需的一切。