我有一個由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中使用集合,所以我對這裏的錯誤感到十分困惑。
向我們展示AddOrUpdateCharacter中的代碼。另外,您的存儲庫如何在控制器中實例化,以及它如何獲得對dbContext的引用? – wllmsaccnt
我已經更新了這個問題。存儲庫和dbcontext由ASP.NET Core的依賴注入系統實例化,所以它們只是在相應的構造函數中初始化的私有字段。我也爲'ConfigureServices()'添加了代碼。 – Telvee32