c# - Entity Framework 核心 : SqlException: A transport-level error has occurred when receiving results from the server

标签 c# entity-framework asp.net-core entity-framework-core

我有一个由 EF Core Code First 数据库支持的基本 ASP.NET Core 应用程序。简而言之,我刚刚添加了一些新功能,用于操作附加到某个父对象的数据对象集合,这些父对象似乎没有任何解释的原因而崩溃。

父对象:

public class Character
{
    public Guid Id { get; set; }
    // int/string properties omitted
    public ICollection<CharacterMerit> CharacterMerits { get; set; }
}

有问题的对象:

public class CharacterMerit
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public Guid CharacterId { get; set; }

    public MeritKey MeritKey { get; set; } // enum
}

此列表在两个地方进行了更新 - 角色创建,以及专用于这些“优点”的单独操作。单独的操作只是将这些 CharacterMerit 对象的列表作为 JSON,确保角色对象存在并将它们扔到存储层。这里没有问题。

启动:

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<ApplicationUser, IdentityRole>(options =>
        {
            options.Password.RequireNonAlphanumeric = false;
        })
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.AddMvc();

    // Add application services.
    services.AddScoped<ISheetsRepository, SheetsRepository>();
    services.AddTransient<IViewModelFactory, ViewModelFactory>();
    services.AddTransient<SeedAdminRole>();
}

存储库:

public bool UpdateMerits(Guid characterId, List<CharacterMerit> merits)
{
    var dbCharacter = _dbcontext.Characters.Include(c => c.CharacterMerits).First(c => c.Id == characterId);

    if (dbCharacter.CharacterMerits.Any())
    {
        _dbcontext.CharacterMerits.RemoveRange(dbCharacter.CharacterMerits);
        dbCharacter.CharacterMerits = null;
        _dbcontext.SaveChanges();
    }

    dbCharacter.CharacterMerits = merits;

    _dbcontext.SaveChanges();

    return true;
}
public bool AddOrUpdateCharacter(Character character, bool date = true)
{
    if (date)
    {
        character.LastUpdated = DateTime.Now;
    }

    if (_dbcontext.Characters.FirstOrDefault(c => c.Id == character.Id) == null)
    {
        _dbcontext.Characters.Add(character);
    }
    else
    {
        _dbcontext.Characters.Update(character);
    }

    _dbcontext.SaveChanges();
    return true;
}

问题出在角色创建上。 创建 Action :

[HttpPost]
public async Task<IActionResult> Create(BasicInfoViewModel viewModel)
{
    var character = new Character
    {
        // property initialisation omitted for brevity
        // Id property is not initialised here, EF does this            
    };

    if(viewModel.Species != "Other")
    {
        character.CharacterMerits = new List<CharacterMerit>();
        character.CharacterMerits.Add(new CharacterMerit
        {
            MeritKey = MeritKey.Default; // for sake of example
        });
    }

    _repository.AddOrUpdateCharacter(character); // just adds the Character object to collection in dbcontext and calls SaveChanges()

    // redirect to another action
}

每当我尝试执行此操作时,我都会收到以下错误(有趣的是,调试器没有捕获到该错误,而是直接进入浏览器,包裹在 DbUpdateException 中)。它似乎在调用 SaveChanges() 时失败了。

System.Data.SqlClient.SqlException: A transport-level error has occurred when receiving results from the server. (provider: Session Provider, error: 19 - Physical connection is not usable)
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error)
at System.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync()
at System.Data.SqlClient.TdsParserStateObject.TryReadNetworkPacket()
at System.Data.SqlClient.TdsParserStateObject.TryPrepareBuffer()
at System.Data.SqlClient.TdsParserStateObject.TryReadByte(Byte& value)
at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
at System.Data.SqlClient.SqlDataReader.get_MetaData()
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior)
at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, String executeMethod, IReadOnlyDictionary`2 parameterValues, Boolean closeConnection)
at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
ClientConnectionId:998c6223-efc9-4172-a344-4b2ba71cf4c9
Error Number:-1,State:0,Class:20

如果我删除添加到 CharacterMerits 列表的代码,一切都会正常运行。 我尝试了什么?

  • 在调用 AddOrUpdateCharacter() 之后移动列表操作
  • 除了首先从 DB 中检索新创建的 Character 对象之外。
  • 初始化一个新列表(而不是在 Controller 中操作 Character 对象)并使用上面的 UpdateMerits() 方法
  • 将存储库设置为 transient 而不是 Startup

我考虑过将此操作重定向到另一个执行此操作的操作,但是从概念的角度来看,此代码属于此操作,它不会解决根本问题(如果有的话)。 应用程序当前在 localdb 上运行,但是也有一个部署版本在标准 SQL Server 数据库上运行。 这不是我第一次在 EF 中使用集合,所以我对这里可能出现的问题感到非常困惑。

最佳答案

此异常似乎表明连接已断开。您使用的是 Azure 还是任何其他云提供商?无论如何,我建议您尝试 connection resiliency EF Core 的特性。

关于c# - Entity Framework 核心 : SqlException: A transport-level error has occurred when receiving results from the server,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45963841/

相关文章:

c# - 为什么我会收到 ""对象“不包含 "Index"的定义”错误?

c# - 将 c# 数组传递给 javascript

c# - 用于接收自动短信通知的 AT 命令

c# - 如何从 Entity Framework Core 中的 DbContext 获取列名和相应的数据库类型

c# - IdentityServer4 - ApiResource 和 Client,它们是如何绑定(bind)在一起的

c# - 如何从 IRandomAccessStream 获取 IBuffer

c# - Entity Framework 级联删除使用linq

c# - 仅在 Azure 计算模拟器中出现 EdmMetadata 错误

c# - 自托管 ASP.NET Core 2.0 : TagHelper doesnt work

c# - VSTS/TFS 设置环境变量 ASP.NET core