c# - 尝试使用 sqlite 在 xamarin 应用程序中进行批量插入时出现异常
问题描述
我开发了代码来获取从我的休息服务发送的 Json。
我收到并威胁代码并生成 sql 插入语句。
我收到了这个错误:
[0:] SQLite.SQLiteException: Constraint
at SQLite.SQLiteCommand.ExecuteNonQuery () [0x000ca] in <84b9c9e630fa45bd8ac799333976ebbf>:0
at GSAN_Mobile.Repository.GsanMobileRepository`1+<>c__DisplayClass9_1[T].<BulkInsert>b__0 (Newtonsoft.Json.Linq.JToken register) [0x0002c] in D:\Projetos\Gsan\mobile\front\GSAN_Mobile\GSAN_Mobile\GSAN_Mobile\Repository\GsanMobileRepository.cs:185
at System.Collections.Generic.List`1[T].ForEach (System.Action`1[T] action) [0x0001e] in <6de48997d0c0445dbea8d4d83492d8c6>:0
at GSAN_Mobile.Repository.GsanMobileRepository`1[T].BulkInsert (Newtonsoft.Json.Linq.JArray array, System.String tableName) [0x00062] in D:\Projetos\Gsan\mobile\front\GSAN_Mobile\GSAN_Mobile\GSAN_Mobile\Repository\GsanMobileRepository.cs:180
我的批量插入方法
public void BulkInsert(JArray array, string tableName = "")
{
try
{
if (string.IsNullOrEmpty(tableName))
{
Type typeParameterType = typeof(T);
tableName = typeParameterType.Name;
}
using (SQLiteConnection connection = new SQLiteConnection(DataBaseUtil.GetDataBasePath()))
{
connection.BeginTransaction();
array.ToList().ForEach(register =>
{
string sql = DataBaseUtil.GenerateInsertStatement(register, tableName);
System.Diagnostics.Debug.WriteLine(sql);
var command = connection.CreateCommand(sql);
command.ExecuteNonQuery();
});
connection.Commit();
DataBaseUtil.CloseConnection(connection);
}
}
catch (Exception e)
{
LogUtil.WriteLog(e);
}
}
我的实用方法
public static string GenerateInsertStatement(JToken register, string tableName)
{
var data = JsonConvert.DeserializeObject<Dictionary<string, string>>(register.ToString());
string columns = string.Join(",", data.Keys.ToList());
string values = string.Join(",", data.Values.Select(v => string.Format(@"'{0}'", v.Trim())));
return string.Format("INSERT INTO {0} ({1}) VALUES ({2}); ", tableName, columns, values);
}
public static void CloseConnection(SQLiteConnection connection)
{
connection.Dispose();
connection.Close();
}
还有我的 ViewModel 类
这是我开始同步时调用的方法
private async Task RegistrarDados()
{
try
{
_logs.Add("Realizando o Download: ");
GenerateAtendimentoMotivosEncerramento();
GenerateHidrometrosLocalInstalacao();
GenerateHidrometrosProtecao();
GenerateFuncionarios();
GenerateGrupoFaturamento();
GenerateLigacaoAguaSituacoes();
GenerateLigacaoEsgotoSituacoes();
GenerateServicosTipo();
GenerateSistemParametros();
GenerateOrdensServico();
//GenerateContas();
int contador = _ordemServicoRepository.Count<OrdemServico>();
_logs.Add("Sincronização encerrada com sucesso!");
await App.Current.MainPage.DisplayAlert("Atenção", "Foram importados " + contador + " Ordens de Serviços!", "OK");
PodeSincronizar = true;
}
catch (Exception e)
{
LogUtil.WriteLog(e);
}
}
这是发生错误的方法
private async void GenerateOrdensServico()
{
try
{
_logs.Add("ORDENS DE SERVIÇO");
int? records = await _ordemServicoRest.GetCount();
int? limit = _sistemaParametroRepository.GetTamanhoPaginaSincMobile();
int? pages = (records / limit);
for (int i = 0; i <= pages; i++)
{
JArray ordensServico = await _ordemServicoRest.GetAllInJsonFormatPaginated(DataBaseUtil.GetPagination(i, limit.Value));
if (ordensServico == null)
{
_logs.Add("Não Contem O.S de Corte para importar!");
await App.Current.MainPage.DisplayAlert("Atenção", "Não tem O.S para importar!", "OK");
continue;
}
_ordemServicoRepository.BulkInsert(ordensServico);
}
}
catch (Exception e)
{
LogUtil.WriteLog(e);
}
}
我收到了分页日期,因为有 8500 个寄存器,有时不会发生错误,但另一方面,我不了解错误。
还有我的模特班
[Serializable]
public class Persistent
{
[AutoIncrement]
[PrimaryKey]
[NotNull]
[JsonProperty("id")]
public int? Id { get; set; }
}
[Table("OrdemServico")]
public class OrdemServico : Persistent
{
[JsonProperty("situacaoOS")]
public int? SituacaoOS { get; set; }
[JsonProperty("idServicoTipo")]
public int? IdServicoTipo { get; set; }
[JsonProperty("dataGeracao")]
public string DataGeracao { get; set; }
[JsonProperty("idRegistroAtendimento")]
public int? IdRegistroAtendimento { get; set; }
[JsonProperty("idgrupo")]
public int? IdGrupo { get; set; }
[JsonProperty("matriculaCliente")]
public int? MatriculaCliente { get; set; }
[JsonProperty("nomeCliente")]
public string NomeCliente { get; set; }
[JsonProperty("tipoLogradouro")]
public string TipoLogradouro { get; set; }
[JsonProperty("logradouro")]
public string Logradouro { get; set; }
[JsonProperty("numeroImovel")]
public int? NumeroImovel { get; set; }
[JsonProperty("numeroCep")]
public int? NumeroCep { get; set; }
[JsonProperty("bairro")]
public string Bairro { get; set; }
[JsonProperty("numeroHidrometro")]
public string NumeroHidrometro { get; set; }
[JsonProperty("idHidrometroProtecao")]
public int? IdHidrometroProtecao { get; set; }
[JsonProperty("idHidrometroLocalInstalacao")]
public int? IdHidrometroLocalInstalacao { get; set; }
[JsonProperty("imovel")]
public int? Imovel { get; set; }
[JsonProperty("ligacaoAguaSituacao")]
public int? LigacaoAguaSituacao { get; set; }
[JsonProperty("ligacaoEsgotoSituacao")]
public int? LigacaoEsgotoSituacao { get; set; }
[JsonProperty("sincronizada")]
public int? Sincronizada { get; set; }
}
我几乎发送了 Id,什么时候我的 API 没有抛出异常。
解决方案
例外及其随机发生的SQLite.SQLiteException: Constraint
事实是关键。您在某处违反了表约束。
您的 SQLite 表需要一个它没有收到的值。例如,如果您的某个数据字段在表中标记为“NOT NULL”,并且您的数据中的某个字段为 NULL,则该约束将失败并且您将收到异常。
您需要确定哪些字段具有约束,然后处理接收到的数据以确保约束完整性。如果表有约束,则将空TEXT
值转换为String.Empty
或将null
INTEGER 字段转换为 0。您将不得不查看数据结构中的设置约束。null
NOT NULL
话虽如此,您应该真正研究参数化查询。您当前的INSERT
声明只是自找麻烦,因为它很容易被注入。例如,如果其中一个value
字符串包含逗号,它可能会破坏您的语句,因为 SQLite 不知道value
它只是一个值,而是将其视为查询命令的一部分。参数解决了这个问题。如果您正确遵循表格约束,这也可能是导致您的问题的原因。
这是一个小示例,说明应如何使用参数构建查询。
cmd.CommandText = "INSERT INTO MyTable (CompanyName, Address) VALUES (@Name, @Address)";
cmd.Parameters.AddWithValue("@CompanyName", myCompanyNameString);
cmd.Parameters.AddWithValue("@Address", myAddressString);
由于我的动态查询值是参数化的,我可以使我的值具有特殊字符或语句,如“DROP TABLE”,它将被正确处理并防止注入攻击或查询中断字符或单词的异常。
推荐阅读
- c# - 在word文档中插入页面?
- mongodb - 如何使用 Spring 从 MongoDB 中检索数据 - 按每天的最新日期时间分组?
- python - 如何将可下载的 TensorFlow 模型发布到 Github
- python - 我该如何解决视图 blog.views.post_detail 没有返回 HttpResponse 对象。它返回 None 而不是
- laravel - Laravel 数据库在部署时出现护照错误
- c# - 一次对多个整数应用位运算符
- python - python ImportError:无法从“covsirphy.cleaning”导入名称“JHUData”
- amazon-web-services - 超时时在 api 网关响应正文中返回 lambda 的 context.requestId
- python - Heroku 无法连接到服务器:连接被拒绝
- c++ - 无限循环问题