EFコアコードファーストDBに基づいた基本的なASP.NETコアアプリケーションがあります。簡単に言えば、いくつかの親オブジェクトにアタッチされたデータオブジェクトのコレクションを操作する新しい機能を少し追加しました。これは明らかに理由がないために転倒しています。エンティティフレームワークコア: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
}
このリストは、2つの場所に更新されます - 文字の作成、およびこれらの 'メリット' に専用の個別アクション。別のアクションでは、これらのオブジェクトのリストを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
リストに追加するコードを削除した場合。 私は何を試しましたか?最初のDBから新しく作成Character
オブジェクトを検索に加えてAddOrUpdateCharacter()呼び出し
- 。
- 私が考えた過渡するリポジトリを設定する代わりに
Startup
にスコープ(代わりにコントローラにCharacter
オブジェクトを操作する)新しいリストを初期化し、
AddOrUpdateCharacterにコードを表示します。また、コントローラでリポジトリをインスタンス化する方法と、dbContextへの参照を取得する方法はありますか? – wllmsaccnt
質問を更新しました。リポジトリとdbcontextは、ASP.NET Coreの依存性注入システムによってインスタンス化されるため、それぞれのコンストラクタで初期化されたプライベートフィールドです。私は 'ConfigureServices()'のコードも追加しました。 – Telvee32