should I use table valued parameter, should I convert my list of objects into a data table.?
"best" is a bit subjective but the list of objects can be provided to the proc as a TVP, JSON string, or XML for a set-based operation in the proc.
A TVP requires a table type in the database with columns matching those of the object fields. The proc TVP declaration specifies that type as a READONLY parameter where it can be used in queries like any other table. The client parameter type for a TVP is SqlDbType.Structured with a value of either IEnumerable<SqlDataRecord>
, DataTable
, or DbDataReader
. A DataTable is most commonly used, at least in my experience, with the columns matching those of the table type. See the ADO.NET Table-Valued Parameters (https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql/table-valued-parameters) topic for code DataTable examples and Erland's Using Table-Valued Parameters article for more info on IEnumerable<SqlDataRecord>
.
Another option in SQL 2016 and later is JSON, which avoids the need to create a table type. The proc JSON parameter can be of type nvarchar(MAX) and used in T-SQL queries with the OPENJSON table-valued function. The app code can simply serialize the object collection as a JSON string (array of json objects) and pass the string value for the parameter value.
The proc could use a MERGE statement for the INSERT/UPDATE. The T-SQL code in your question looks a bit odd since I don't understand your schema or use case, but below are untested examples with dummy data types to show how you could use MERGE with a TVP or JSON.
--TVP example
MERGE dbo.DetailFPlantbl AS target
USING @DetailFPlantbl AS source ON
source.IDtoUpdate = target.IDtoUpdate
AND target.DActualcumSAP IS NULL
AND target.DActualcumtotal IS NULL
AND target.DActualperdaySAP IS NULL
WHEN MATCHED THEN UPDATE SET
DTargetcum = source.DTargetcum
, DTargetperday = source.DTargetperday
, DTargetcumtotal = source.DTargetcumtotal
, DActualcumSAP = source.DActualcumSAP
, DActualperdaySAP = source.DActualperdaySAP
, DActualcumtotal = source.DActualcumtotal
, TimeStampFP = CURRENT_TIMESTAMP
WHEN NOT MATCHED BY TARGET THEN INSERT (
PlanDate
, ProcessUnitID
, IDtoUpdate
)
VALUES (
source.PlanDate
, source.ProcessUnitID
, source.IDtoUpdate
);
--JSON example
MERGE dbo.DetailFPlantbl AS target
USING (
SELECT
IDtoUpdate
, DTargetcum
, DTargetperday
, DTargetcumtotal
, DActualcumSAP
, DActualperdaySAP
, DActualcumtotal
, TimeStampFP
, PlanDate
, ProcessUnitID
FROM OPENJSON(@DetailFPlantbl)
WITH (
IDtoUpdate int
, DTargetcum int
, DTargetperday int
, DTargetcumtotal int
, DActualcumSAP int
, DActualperdaySAP int
, DActualcumtotal int
, TimeStampFP datetime2
, PlanDate datetime2
, ProcessUnitID int
)
)
AS source ON
source.IDtoUpdate = target.IDtoUpdate
AND target.DActualcumSAP IS NULL
AND target.DActualcumtotal IS NULL
AND target.DActualperdaySAP IS NULL
WHEN MATCHED THEN UPDATE SET
DTargetcum = source.DTargetcum
, DTargetperday = source.DTargetperday
, DTargetcumtotal = source.DTargetcumtotal
, DActualcumSAP = source.DActualcumSAP
, DActualperdaySAP = source.DActualperdaySAP
, DActualcumtotal = source.DActualcumtotal
, TimeStampFP = CURRENT_TIMESTAMP
WHEN NOT MATCHED BY TARGET THEN INSERT (
PlanDate
, ProcessUnitID
, IDtoUpdate
)
VALUES (
source.PlanDate
, source.ProcessUnitID
, source.IDtoUpdate
);