Error when saving a date column to the underlying database using sqlitedatadapter - vb.net

I would appreciate any help in finding why I get an error when saving back to a database. The error is: "Concurrency violation: the UpdateCommand affected 0 of the expected 1 records."
I have worked out that the error only occurs when my table has a date field which I fill from the underlying database use a sqlitedatadapter as follows:
Public connstring As String = "Data Source=c:\VS-2019\SaveTable\SaveTable\Data\TestDb.db"
Public conn As New SQLiteConnection
Public Sub FillMainTables()
conn.ConnectionString = connstring
conn.Open()
DTAllCustomers.Rows.Clear()
sql = "SELECT * FROM Customers"
AllCustomersAdapter = New SQLiteDataAdapter(sql, conn)
AllCustomersAdapter.Fill(DTAllCustomers)
End Sub
I then modify a few records in the datatable(DTAllCustomers) using this code
For i = 0 To DTAllCustomers.Rows.Count - 1
If DTAllCustomers.Rows(i).Item("sitecode") = "RESI" Then
DTAllCustomers.Rows(i).Item("Email") = "Changed"
End If
Next
I then try to save the modified table back to the underlying database with:
Dim cbAllCustomers As New SQLiteCommandBuilder(AllCustomersAdapter)
AllCustomersAdapter.UpdateCommand = cbAllCustomers.GetUpdateCommand
Try
AllCustomersAdapter.Update(DTAllCustomers)
Catch ex As Exception
MsgBox(ex.Message)
End Try
When I remove the DATETIME columns in DTAllCustomers the error disappears and the update completes correctly. Does SQLite change the date structure/value of the DateTime columns between filling the datatable and saving back to the datatable?
UpdateCommand.CommandText is:
UPDATE [main].[sqlite_default_schema].[Customers] SET [Email] = #param1
WHERE (([PrimaryKey] = #param2)
AND ([CustomerNumber] = #param3)
AND ((#param4 = 1 AND [Zone] IS NULL) OR ([Zone] = #param5))
AND ((#param6 = 1 AND [SiteCode] IS NULL) OR ([SiteCode] = #param7))
AND ((#param8 = 1 AND [FirstName] IS NULL) OR ([FirstName] = #param9))
AND ((#param10 = 1 AND [Surname] IS NULL) OR ([Surname] = #param11))
AND ((#param12 = 1 AND [Villa] IS NULL) OR ([Villa] = #param13))
AND ((#param14 = 1 AND [Village] IS NULL) OR ([Village] = #param15))
AND ((#param16 = 1 AND [Address] IS NULL) OR ([Address] = #param17))
AND ((#param18 = 1 AND [Suburb] IS NULL) OR ([Suburb] = #param19))
AND ((#param20 = 1 AND [PostCode] IS NULL) OR ([PostCode] = #param21))
AND ((#param22 = 1 AND [Phone] IS NULL) OR ([Phone] = #param23))
AND ((#param24 = 1 AND [Mobile1] IS NULL) OR ([Mobile1] = #param25))
AND ((#param26 = 1 AND [Mobile2] IS NULL) OR ([Mobile2] = #param27))
AND ((#param28 = 1 AND [Email] IS NULL) OR ([Email] = #param29))
AND ((#param30 = 1 AND [System] IS NULL) OR ([System] = #param31))
AND ((#param32 = 1 AND [Panels] IS NULL) OR ([Panels] = #param33))
AND ((#param34 = 1 AND [Isolator] IS NULL) OR ([Isolator] = #param35))
AND ((#param36 = 1 AND [Inverter] IS NULL) OR ([Inverter] = #param37))
AND ((#param38 = 1 AND [SolarHotWater] IS NULL) OR ([SolarHotWater] = #param39))
AND ((#param40 = 1 AND [Skylight] IS NULL) OR ([Skylight] = #param41))
AND ((#param42 = 1 AND [Rebate] IS NULL) OR ([Rebate] = #param43))
AND ((#param44 = 1 AND [Quote] IS NULL) OR ([Quote] = #param45))
AND ((#param46 = 1 AND [Notes] IS NULL) OR ([Notes] = #param47))
AND ((#param48 = 1 AND [LastCleaned] IS NULL) OR ([LastCleaned] = #param49))
AND ((#param50 = 1 AND [BookedInDate] IS NULL) OR ([BookedInDate] = #param51))
AND ((#param52 = 1 AND [BookedInOrder] IS NULL) OR ([BookedInOrder] = #param53))
AND ((#param54 = 1 AND [Frequency] IS NULL) OR ([Frequency] = #param55))
AND ((#param56 = 1 AND [NextCallDue] IS NULL) OR ([NextCallDue] = #param57))
AND ((#param58 = 1 AND [Status] IS NULL) OR ([Status] = #param59))
AND ((#param60 = 1 AND [Source] IS NULL) OR ([Source] = #param61)))
The parameter values and the date columns are in this format - #5/30/2018 12:00:00 AM#, however in the command text there is a #paramX = 1 for each column in the table and the paramX being passed has a value of 0.

Related

Filter only get one condition

I have a validation in WHERE clause like:
...
AND (#BDOnly = 0
OR [DT].[Abbreviation] = #IsBDChecked)
AND (#CDOnly = 0
OR [DT].[Abbreviation] = #IsCDChecked)
AND (#PPOOnly = 0
OR [DT].[Abbreviation] = #IsPPOChecked)
AND (#FBOMOnly = 0
OR [DT].[Abbreviation] = #IsFBOMChecked)
AND (#APOnly = 0
OR [DT].[Abbreviation] = #IsAPChecked)
AND (#COOnly = 0
OR [DT].[Abbreviation] = #IsCOChecked)
So each AND clause check if boolean is bit value is 0 or 1, if it's 0 just do any but if it's 1 it do a filter. My problem is
if I'm sending two with value 1, I mean
#BDOnly = 1 and #CDOnly = 1 it only filter one of them instead get two filters I mean:
[DT].[Abbreviation] = #IsBDChecked
and
[DT].[Abbreviation] = #IsCDChecked
What am I doing wrong? Regards
I'm going to take a guess here because there's not enough data. If you want to return a row where Abbreviation matched #IsBDChecked only when #BDOnly is set, and also another row where Abbreviation matches #IsCDChecked when #CDOnly is set, try this:
(#BDOnly = 1
AND [DT].[Abbreviation] = #IsBDChecked)
OR (#CDOnly = 1
AND [DT].[Abbreviation] = #IsCDChecked)
OR (#PPOOnly = 1
AND [DT].[Abbreviation] = #IsPPOChecked)
OR (#FBOMOnly = 1
AND [DT].[Abbreviation] = #IsFBOMChecked)
OR (#APOnly = 1
AND [DT].[Abbreviation] = #IsAPChecked)
OR (#COOnly = 1
AND [DT].[Abbreviation] = #IsCOChecked)
Small representative case:
DECLARE #ADOnly BIT = 0
, #BDOnly BIT = 1
, #CDOnly BIT = 1
, #IsADChecked NVARCHAR(100) = 'A'
, #IsCDChecked NVARCHAR(100) = 'C'
, #IsBDChecked NVARCHAR(100) = 'B'
;WITH myTable AS
(
SELECT * FROM (VALUES ('A'), ('B'), ('C')) X(Abbreviation)
)
SELECT *
FROM myTable
WHERE (#ADOnly = 1 AND Abbreviation = #IsADChecked)
OR (#BDOnly = 1 AND Abbreviation = #IsBDChecked)
OR (#CDOnly = 1 AND Abbreviation = #IsCDChecked)
Yields:
Abbreviation
------------
B
C

Catching last datetime after update wont result

I have the following code:
UPDATE sm
SET sm_fecha_venc = (SELECT MIN(nd_fecha_venc) FROM [db_facturacion].[dbo].[tb_notas_debito]
WHERE sm_codigo = nd_num_servicio
-- AND nd_referencia = sm_cod_producto
AND nd_num_factura = sm_cod_factura
AND nd_estado = 'G')
,sm_fecha_ult_pago = (SELECT MAX(nd_fecha_pago) FROM [db_facturacion].[dbo].[tb_notas_debito]
WHERE sm_codigo = nd_num_servicio
-- AND nd_referencia = sm_cod_producto
AND nd_num_factura = sm_cod_factura
AND nd_estado = 'C')
,sm_fecha = GETDATE()
,sm_cod_factura_ren = #i_num_factura
OUTPUT DELETED.sm_fecha_venc AS FECHA_VENC_OLD,
DELETED.sm_fecha_ult_pago AS FECHA_ULT_PAGO_OLD,
DELETED.sm_fecha AS FECHA_OLD,
DELETED.sm_cod_factura_ren AS COD_FACTURA_REN_OLD
INTO #TABLATABLA --
FROM [db_facturacion].[dbo].[tb_servicios] sm --WITH(NOLOCK)
INNER JOIN #servicios AS T ON sm_codigo = num_servicio
WHERE sm_tipo_bien_protegido = 1
AND [sm_estado] = 1
--AND sm.sm_cod_forma_contrato = 1
AND sm.sm_tipo_inventario = tipo_inventario
/*===========================
INSERTED DELETED
=============================*/
UPDATE db_facturacion.[dbo].[tb_log_cambio_servicio]
SET cs_fecha_venc_old = FECHA_VENC_OLD
,cs_fecha_ult_pago_old = FECHA_ULT_PAGO_OLD
,cs_fecha_old = FECHA_OLD
,cs_cod_factura_ren_old = COD_FACTURA_REN_OLD
FROM #TABLATABLA
WHERE cs_codigo = #ID_ULTIMO_ING (LAST ##IDENTITY)
Im trying to save the last dates into a log table, just in case I have to return those dates back.
The code works good, just that it's catching the actual date and inserted in the log table.
What am I missing?

SQL / VB.NET - Query doesn't return to application

I've got a MSSQL procedure running fine from the SQL Management console, but when I try to run it from my VB.NET it simply never returns. Someone have any idea?
I am testing with the same database.
SQL CODE (PROCEDURE)
ALTER PROCEDURE [dbo].[P_DEN_L_IMPRESSAO_ORCAMENTOS_APROVADO_NOVO]
(
#PAC_D_DATA_INICIAL DATETIME = NULL,
#PAC_D_DATA_FINAL DATETIME = NULL,
#PAC_DET_N_CODIGO DECIMAL = NULL,
#PAC_CLI_N_CODIGO DECIMAL = NULL,
#PAC_EMP_N_CODIGO DECIMAL = NULL
)
AS
SELECT
PAC_N_CODIGO,
PAC_C_CODIGO_INTERNO,
PAC_C_NOME,
PAC_C_EMAIL,
PAC_C_TELEFONE_RES,
PAC_CLI_N_CODIGO,
CLI_C_DESCRICAO,
ODO_D_DATA_INICIO,
ODO_D_DATA_FINAL,
ODO_PTR_N_CODIGO,
CASE PAC_N_CORRESPONDENCIA
WHEN 1 THEN
PAC_C_ENDERECO_RES +
CASE
WHEN PAC_C_NUMERO_RES IS NULL OR PAC_C_NUMERO_RES = '' THEN ''
ELSE ', ' + PAC_C_NUMERO_RES
END +
CASE
WHEN PAC_C_COMPLEMENTO_RES IS NULL OR PAC_C_COMPLEMENTO_RES = '' THEN ''
ELSE ', ' + PAC_C_COMPLEMENTO_RES
END
WHEN 2 THEN
PAC_C_ENDERECO_COM +
CASE
WHEN PAC_C_NUMERO_COM IS NULL OR PAC_C_NUMERO_COM = '' THEN ''
ELSE ', ' + PAC_C_NUMERO_COM
END +
CASE
WHEN PAC_C_COMPLEMENTO_COM IS NULL OR PAC_C_COMPLEMENTO_COM = '' THEN ''
ELSE ', ' + PAC_C_COMPLEMENTO_COM
END
END AS PAC_C_ENDERECO,
CASE PAC_N_CORRESPONDENCIA
WHEN 1 THEN PAC_C_BAIRRO_RES
WHEN 2 THEN PAC_C_BAIRRO_COM
END AS PAC_C_BAIRRO,
CASE PAC_N_CORRESPONDENCIA
WHEN 1 THEN PAC_C_CIDADE_RES
WHEN 2 THEN PAC_C_CIDADE_COM
END AS PAC_C_CIDADE,
CASE PAC_N_CORRESPONDENCIA
WHEN 1 THEN
(SELECT EST_C_RESUMIDO
FROM DEN_EST_ESTADO
WHERE EST_N_CODIGO = PAC_EST_N_CODIGO_RES)
WHEN 2 THEN
(SELECT EST_C_RESUMIDO
FROM DEN_EST_ESTADO
WHERE EST_N_CODIGO = PAC_EST_N_CODIGO_COM)
END AS EST_C_RESUMIDO,
CASE PAC_N_CORRESPONDENCIA
WHEN 1 THEN PAC_C_CEP_RES
WHEN 2 THEN PAC_C_CEP_COM
END AS PAC_C_CEP,
ODO_N_VERSAO,
PAC_C_CELULAR,
PAC_DET_N_CODIGO,
ODO_N_CODIGO,
SUM(VIN_N_VALOR) as 'T_PROC',
(SELECT SUM(VIN_N_VALOR) FROM DEN_VIN_VINCULO_TRATAMENTO
WHERE VIN_OXD_ODO_N_CODIGO = ODO_N_CODIGO) as 'VIN_N_VALOR',
convert(decimal(18,2),0) AS 'T_ENTRADA'
FROM
DEN_PAC_PACIENTE
INNER JOIN
DEN_DET_DENTISTA
ON
DET_N_CODIGO = PAC_DET_N_CODIGO
AND
DET_CLI_N_CODIGO = PAC_CLI_N_CODIGO
INNER JOIN
DEN_CLI_CLINICA
ON
CLI_N_CODIGO = PAC_CLI_N_CODIGO
INNER JOIN
DEN_EMP_EMPRESA
ON
EMP_N_CODIGO = CLI_EMP_N_CODIGO
INNER JOIN
DEN_ODO_ODONTOGRAMA
ON
ODO_PAC_N_CODIGO = PAC_N_CODIGO
INNER JOIN
DEN_VIN_VINCULO_TRATAMENTO
ON
VIN_OXD_ODO_N_CODIGO = ODO_N_CODIGO
WHERE
(ODO_D_DATA_FINAL BETWEEN #PAC_D_DATA_INICIAL AND #PAC_D_DATA_FINAL)
AND
(ODO_PTR_N_CODIGO = 2)
AND
(ODO_B_APROVADO = 1)
AND
(#PAC_CLI_N_CODIGO IS NULL OR PAC_CLI_N_CODIGO = #PAC_CLI_N_CODIGO)
AND
(#PAC_DET_N_CODIGO IS NULL OR VIN_DET_N_CODIGO = #PAC_DET_N_CODIGO)
AND
(CLI_EMP_N_CODIGO = #PAC_EMP_N_CODIGO)
AND
(PAC_B_ATIVO = 1)
AND
(PAC_B_POTENCIAL = 0)
GROUP BY
PAC_N_CODIGO,
PAC_C_CODIGO_INTERNO,
PAC_C_NOME,
PAC_C_EMAIL,
PAC_C_TELEFONE_RES,
PAC_CLI_N_CODIGO,
CLI_C_DESCRICAO,
ODO_D_DATA_INICIO,
ODO_D_DATA_FINAL,
ODO_PTR_N_CODIGO,
ODO_N_VERSAO,
PAC_C_CELULAR,
PAC_DET_N_CODIGO,
ODO_N_CODIGO,
PAC_N_CORRESPONDENCIA,
PAC_C_ENDERECO_RES,
PAC_C_NUMERO_RES,
PAC_C_NUMERO_RES,
PAC_C_COMPLEMENTO_RES,
PAC_C_ENDERECO_COM,
PAC_C_NUMERO_COM,
PAC_C_COMPLEMENTO_COM,
PAC_C_BAIRRO_RES,
PAC_C_BAIRRO_COM,
PAC_C_CIDADE_RES,
PAC_C_CIDADE_COM,
PAC_EST_N_CODIGO_RES,
PAC_EST_N_CODIGO_COM,
PAC_C_CEP_RES,
PAC_C_CEP_COM
ORDER BY
PAC_C_NOME, ODO_N_VERSAO
VB.NET CODE
Public Function ListarOrcamentosAprovadoNovo(ByVal mdlPaciente As Paciente, _
ByVal datDataInicial As Date, _
ByVal datDataFinal As Date, _
ByVal pblnEtiqueta As Boolean, Optional ByVal pstrCodigos As String = "") As DataTable
Try
cmdCommand = New FWCommand
With cmdCommand
.CommandText = "P_DEN_L_IMPRESSAO_ORCAMENTOS_APROVADO_NOVO"
.CommandTimeout = intCommandTimeOut
.CommandType = CommandType.StoredProcedure
.Parameters.Add(New FWParameter("#PAC_D_DATA_INICIAL", FWDbType.DateTime))
.Parameters("#PAC_D_DATA_INICIAL").Value = datDataInicial
.Parameters.Add(New FWParameter("#PAC_D_DATA_FINAL", FWDbType.DateTime))
.Parameters("#PAC_D_DATA_FINAL").Value = datDataFinal
If mdlPaciente.CodDentista > -1 Then
.Parameters.Add(New FWParameter("#PAC_DET_N_CODIGO", FWDbType.Decimal))
.Parameters("#PAC_DET_N_CODIGO").Value = mdlPaciente.CodDentista
End If
If mdlPaciente.CodClinica > 0 Then
.Parameters.Add(New FWParameter("#PAC_CLI_N_CODIGO", FWDbType.Decimal))
.Parameters("#PAC_CLI_N_CODIGO").Value = mdlPaciente.CodClinica
End If
If mdlPaciente.CodEmpresa > 0 Then
.Parameters.Add(New FWParameter("#PAC_EMP_N_CODIGO", FWDbType.Decimal))
.Parameters("#PAC_EMP_N_CODIGO").Value = mdlPaciente.CodEmpresa
End If
End With
Return conProvider.ExecuteDataTable(cmdCommand)
Catch ex As Exception
Throw
Finally
cmdCommand = Nothing
End Try
End Function
Things to check:
Check that your .NET connection string is pointing to the same database that
you are using in your SSMS query
You are using different parameter values in you .NET code then when running in SSMS
This could be related to "parameter sniffing". Possible workarounds are
a) adding with(recompile) to the proc,
b) add a set of local variables that you copy the parameter values into and use the local variables in the query,
c) use OPTION (OPTIMIZE FOR (#VARIABLE UNKNOWN)), or
d) trace flag 4136 that can be used to disable the "parameter sniffing" process (http://support.microsoft.com/kb/980653)
See these articles for more details on parameter sniffing:
http://blogs.msdn.com/b/turgays/archive/2013/09/10/parameter-sniffing-problem-and-workarounds.aspx
http://blogs.technet.com/b/mdegre/archive/2012/03/19/what-is-parameter-sniffing.aspx

SQL Boolean Vars in Where stament

I am making an rdl report and I have three check-boxes that if checked need to alter my WHERE statement. If none are checked the result should only match by date range. If one or more are checked it needs to return the fields that match the variables corresponding string.
WHERE
(EffectiveDate BETWEEN #StartDate AND #EndDate)
AND (((#IncludeSEWPrefix = 1 AND PrefixId = 'SEW') OR #IncludeSEWPrefix = 0)
AND ((#IncludePAWPrefix = 1 AND PrefixId = 'PAW') OR #IncludePAWPrefix = 0)
AND ((#IncludeRPLPrefix = 1 AND PrefixId = 'RPL') OR #IncludeRPLPrefix = 0))
My code so far works when none are checked and when one is checked, but returns nothing when more than one check-box has been checked. So to try and fix this I altered the code to this
WHERE
(EffectiveDate BETWEEN #StartDate AND #EndDate)
AND ((((#IncludeSEWPrefix = 1 AND PrefixId = 'SEW') OR #IncludeSEWPrefix = 0)
OR ((#IncludePAWPrefix = 1 AND PrefixId = 'PAW') OR #IncludePAWPrefix = 0)
OR ((#IncludeRPLPrefix = 1 AND PrefixId = 'RPL') OR #IncludeRPLPrefix = 0)))
Which resulted in all rows being returned no matter what was selected. Can someone tell me where I am going wrong?
I believe this is the correct rearrangement. Trickier problem than it first appears. The issue was seperating lines like ((#IncludeSEWPrefix = 1 AND PrefixId = 'SEW') OR #IncludeSEWPrefix = 0) with AND meant that if two includes were true, a row would need to have both PrefixId's, which can't happen. And if you separated them with OR, then having just one include false, means that every row will pass. So instead, check that a row has the prefix of any that are included, otherwise all includes have to be off.
WHERE EffectiveDate BETWEEN #StartDate AND #EndDate
AND
(
(#IncludeSEWPrefix = 1 AND PrefixId = 'SEW') OR
(#IncludePAWPrefix = 1 AND PrefixId = 'PAW') OR
(#IncludeRPLPrefix = 1 AND PrefixId = 'RPL') OR
(#IncludeSEWPrefix = 0 AND #IncludePAWPrefix = 0 AND #IncludeRPLPrefix = 0)
)
Try this
WHERE
(EffectiveDate BETWEEN #StartDate AND #EndDate)
AND
(
(#IncludeSEWPrefix = 1 AND PrefixId = 'SEW' OR #IncludeSEWPrefix = 0) AND
(#IncludePAWPrefix = 1 AND PrefixId = 'PAW' OR #IncludePAWPrefix = 0) AND
(#IncludeRPLPrefix = 1 AND PrefixId = 'RPL' OR #IncludeRPLPrefix = 0)
)
You have more parenthesis than needed, it does not hurt but just be aware.
Maybe this can help:
WHERE (EffectiveDate BETWEEN #StartDate AND #EndDate)
AND ( ((#IncludeSEWPrefix = 1 AND PrefixId = 'SEW') OR (#IncludeSEWPrefix = 0 AND #PrefixId <> 'SEW'))
OR ((#IncludePAWPrefix = 1 AND PrefixId = 'PAW') OR (#IncludePAWPrefix = 0 AND #PrefixId <> 'PAW'))
OR ((#IncludeRPLPrefix = 1 AND PrefixId = 'RPL') OR (#IncludeRPLPrefix = 0 AND #PrefixId <> 'RPL'))
)

SELECT FROM depending on a parameter in SQL

I want to obtain from a parameter, #Display the value 0, 1 or 2. When #Display = 0, I want to display all the items for which ec.IsEquipmentRelated is true. When #Display = 0, I want to display all the items for which ec.IsEquipmentRelated is false and when #Display = 2, I want to display all the items for which ec.IsEquipmentRelated is true OR false. How can I implement this in the FROM section?
ALTER PROCEDURE [dbo].[Downtime_GetNewCause_EquimentLocation]
#DisplayInactive bit = 0,
#SortOrder INT = 0,
#Diplay INT = 0
AS
-- Main Data source
SELECT ic.IncidentCauseID
, 'EquimentRelated' = COALESCE(ec.IsEquipmentRelated, 0)
, ic.NewIncidentCauseID
, ic.DisplayName
, ic.IsLegacy
, el.EquipmentLocationID
, el.ShopID
, ec.EquipmentClassID
, ec.EquipmentAbbr
, el.ClassSequenceNumber
, el.EquipmentComponent
, el.CompSequenceNumber
, ic.IsActive
FROM Downtime_IncidentCauses ic
LEFT JOIN Downtime_EquipmentLocations el ON ic.EquipmentLocationID = el.EquipmentLocationID
LEFT JOIN Downtime_EquipmentClasses ec ON el.EquipmentClassID = ec.EquipmentClassID AND
CASE WHEN #Diplay = 0 THEN ...
CASE WHEN #Diplay = 1 THEN ...
CASE WHEN #Diplay = 2 THEN ...
This should work:
INNER JOIN Downtime_EquipmentClasses ec
ON (el.EquipmentClassID = ec.EquipmentClassID)
AND ( (#Display = 0 AND ec.IsEquipmentRelated = 1)
OR (#Display = 1 AND ec.IsEquipmentRelated = 0)
OR (#Display = 2) )
Do it in a WHERE clause:
WHERE (#Display = 0 AND ec.IsEquipmentRelated = 'True')
OR (#Display = 1 AND ec.IsEquipmentRelated = 'False')
OR #Display = 2