2017-08-30 28 views
0

我有一個由EF Core Code First DB支持的基本ASP.NET Core應用程序。簡而言之,我剛剛添加了一些新功能,這些功能可以處理附加到某個父對象的數據對象集合,這些對象似乎沒有可解釋的原因。實體框架Core:SqlException:從服務器接收結果時發生傳輸級錯誤

父對象:

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; 
} 

的問題是在角色創造。每當我試圖執行這個動作,我得到以下錯誤(其中,有趣的是,不被抓住了調試,只是徑直到瀏覽器,裹在DbUpdateException

[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 
} 

: 創建行動。它似乎在撥打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對象。
  • 正在初始化一個新的列表(而不是操作在控制器中的Character對象),並使用UpdateMerits()方法上述
  • 設置存儲庫瞬態,而不是在Startup

作用域我已經考慮過讓這個動作重定向到另一個可以執行此操作的動作,然而從概念的角度來看,這個代碼屬於這個動作,並且如果存在的話,它不會解決一個基本問題。 應用程序當前正在localdb上運行,但也有一個在標準SQL Server數據庫上運行的部署版本。 這不是我第一次在EF中使用集合,所以我對這裏的錯誤感到十分困惑。

+2

向我們展示AddOrUpdateCharacter中的代碼。另外,您的存儲庫如何在控制器中實例化,以及它如何獲得對dbContext的引用? – wllmsaccnt

+0

我已經更新了這個問題。存儲庫和dbcontext由ASP.NET Core的依賴注入系統實例化,所以它們只是在相應的構造函數中初始化的私有字段。我也爲'ConfigureServices()'添加了代碼。 – Telvee32

回答

0

此異常似乎表明連接已斷開。您是否在使用Azure或任何其他雲提供商?無論如何,我建議你嘗試一下EF Core的connection resiliency功能。

+0

這是在localdb實例上,部署的版本位於GearHost上(顯然它基於Azure鬆散),但是此代碼尚未生效。 – Telvee32

+0

爲什麼不嘗試連接彈性功能? –

+0

實際上,哇,謝謝。在這種情況下,真正的問題是爲什麼連接會被丟棄? – Telvee32

相關問題