以下のエラーが発生している列を特定しようとしています。サードパーティのサービスによって提供された受信データについて何かが変更され、SQLに保存しようとすると失敗するようになりました。
Microsoft.EntityFrameworkCore.DbUpdateException:エントリの更新中にエラーが発生しました。詳細については、内部例外を参照してください。---> System.Data.SqlClient.SqlException:数値をデータ型数値に変換する際の算術オーバーフローエラー。ステートメントは終了されました。
非常に単純なフロー:
データ構造は次のように定義されます。
[JsonObject(MemberSerialization.OptIn)]
public class RatDbAttributes
{
[JsonProperty]
[StringLength(50)]
public string block_chain { get; set; } // varchar(50)
[JsonProperty]
[StringLength(50)]
public string block_reduction { get; set; } // varchar(50)
[JsonProperty]
[StringLength(50)]
public string block_reward { get; set; } // varchar(50)
[JsonProperty]
public double block_time { get; set; } // decimal(28,6)
[JsonProperty]
[StringLength(100)]
public string consensus_method { get; set; } // varchar(100)
[JsonProperty]
public decimal decimals { get; set; } // decimal(28,6)
[JsonProperty]
[StringLength(50)]
public string difficulty_retarget { get; set; } // varchar(50)
[JsonProperty]
[StringLength(200)]
public string genesis_address { get; set; } // varchar(200)
[JsonProperty]
[StringLength(100)]
public string hash_algorithm { get; set; } // varchar(100)
[JsonProperty]
[StringLength(50)]
public string mineable { get; set; } // varchar(50)
[JsonProperty]
public long p2p_port { get; set; } // bigint
[JsonProperty]
public long rpc_port { get; set; } // bigint
[JsonProperty]
[StringLength(200)]
public string token_role { get; set; } // varchar(200)
[JsonProperty]
public decimal @float { get; set; } // decimal(28,6)
[JsonProperty]
public decimal minted { get; set; } // decimal(28,6)
[JsonProperty]
public decimal total_supply { get; set; } // decimal(28,6)
[JsonProperty]
public decimal max_supply { get; set; } // decimal(28,6)
[JsonProperty]
[StringLength(133)]
public string wallet { get; set; } // varchar(133)
[JsonProperty]
[NotMapped]
public double genesis_timestamp { get; set; } // see below
[JsonIgnore]
public DateTime Genesis_TimeStamp { get { return genesis_timestamp.ToDateTime(); } set { genesis_timestamp = value.ToEpoch(); } }
// Foregin Key Relationship (1-to-1) and Primary Key
[JsonIgnore]
public long TokenMasterId { get; set; }
[JsonIgnore]
[ForeignKey("TokenMasterId")]
public RatDbTokenMaster TokenMaster { get; set; } //foreign key to Parent
}
私はダブルチェックしましたがgenesis_timestamp
、それは問題ではありません(ダブルを日時に変換する)。
着信失敗JSONのサンプル:
{"block_chain":""
,"block_reduction":""
,"block_reward":"0"
,"block_time":0.0
,"consensus_method":""
,"decimals":0.0
,"difficulty_retarget":""
,"genesis_address":""
,"hash_algorithm":""
,"mineable":"False"
,"p2p_port":0
,"rpc_port":0
,"token_role":""
,"float":0.0
,"minted":0.0
,"total_supply":0.0
,"max_supply":0.0
,"wallet":""
,"genesis_timestamp":0.0
}
バッチが失敗した場合のフェイルオーバー反復保存を作成しました。このクラスのデータベース接続を「グローバル」にしたので、うっかりして問題が発生しました。レコードセットを追加して保存しようとし(エラーポップ)、問題のあるレコードを見つけるために、ますます小さなバッチを繰り返してみます。問題は、反復する前に問題のあるレコードセットを削除しなかったことです。したがって、すべての反復でDB接続にエラー状態が発生しました。
internal void IterateSave<TModel>(List<TModel> items) where TModel : class
{
using (LogContext.PushProperty("Data: Class", nameof(RatBaseCommandHandler)))
using (LogContext.PushProperty("Data: Method", nameof(IterateSave)))
using (LogContext.PushProperty("Data: Model", nameof(items)))
{
int max = items.Count;
int skip = 0;
int take = (max > 20) ? (max / 5) : 1;
int lastTake = take;
List<TModel> subItems = new List<TModel>();
while (skip <= max)
{
try
{
subItems = items.Skip(skip).Take(take).ToList();
Log.Verbose("Working {Max} | {Take} | {Skip}", max, take, skip);
skip += take;
_db.Set<TModel>().AddRange(subItems);
_db.SaveChanges();
}
catch (Exception ex)
{
/***** Was not removing the faulty record/recordset! *****/
_db.Set<TModel>().RemoveRange(subItems);
/***** Was not removing the faulty record/recordset! *****/
if (take == 1 && skip < max)
{
Log.Error(ex, "Error saving specific record in this data batch! {GuiltyRecord}", JsonConvert.SerializeObject(subItems));
if (skip >= max - 1)
{
depth--;
return;
}
}
else if (take > 1)
{
Log.Warning("Something is wrong saving this data batch! {RecordCount} Running a smaller batch to isolate.", take);
IterateSave(subItems);
}
}
}
}
}
これらの2行が追加されると(catchのコメントセクション)、エラーは文字通りすぐに飛び出しました!
このデータバッチに特定のレコードを保存するときにエラーが発生しました。"[{\" block_chain \ ":\" Ethereum \ "、\" block_reduction \ ":\" \ "、\" block_reward \ ":\" 0 \ "、\" block_time \ ":0.0、\" consensus_method \ ":\" \ "、\" decimals \ ":18.0、\" difficulty_retarget \ ":\" \ "、\" genesis_address \ ":\" 0x3520ba6a529b2504a28eebda47d255db73966694 \ "、\" hash_algorithm \ ":\" \ "、\ "mineable \":\ "False \"、\ "p2p_port \":0、\ "rpc_port \":0、\ "token_role \":\ "\"、\ "float \":0.0、\ "minted \ ":60000000000000000000000000.0、\" total_supply \ ":60000000000000000000000000.0、\" max_supply \ ":60000000000000000000000000.0、\" wallet \ ":\" \ "、\" Genesis_timestamp \ ":0.0}]" Microsoft.EntityFrameworkCore.DbUpdateException:エントリの更新中にエラーが発生しました。詳細については、内部例外を参照してください。---> System.Data.SqlClient.SqlException:数値をデータ型数値に変換する際の算術オーバーフローエラー。ステートメントは終了されました。
C#はDECIMALデータ型で60000000000000000000000000.0を処理できますが、SQLはDECIMAL(28,6)で定義されています。6桁の精度のため、10 ^ 22の値のスペースしか残されません。
(SQLがDECIMAL(38,6)を処理できるようになりました。実動データを失うことなく列定義を試す時間です。)
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加