The bounty expires in 10 hours. Answers to this question are eligible for a +150 reputation bounty. CodeMan03 wants to draw more attention to this question.
I have a child table that rerferences a parent table with a 1 to many relationship. PK -> multiple foreign keys. The reason is the FK table are a list of objects related to an ID on the parent table.
How can I use dapper to insert multiple rows with the same FK?
assessmentModel.locationInformationModels = new List<LocationInformationModel>();
string sqlStatement = @"INSERT INTO LocationInformation
([LocationInformationId]
,[Address1]
,[Address2]
,[City]
,[State]
,[Zip])
VALUES(
@LocationInformationId,@Address1,@Address2,@City,@State,@Zip)";
using (var connection = new SqlConnection(_connectionString))
{
await connection.OpenAsync();
using (var ts = connection.BeginTransaction())
{
var retVal = await connection.ExecuteAsync(sqlStatement, assessmentModel.locationInformationModels, transaction:ts);
ts.Commit();
return retVal;
}
}
2条答案
按热度按时间qlvxas9a1#
The question is a bit unclear. The code shows inserting a list of items without anything that looks like a foreign key. In any case, Dapper is a microORM, it doesn't handle relations between entities, or auto-update keys. It won't change the supplied SQL statement to handle multiple objects either.
I suspect the real question is how to return a generated value from the database, eg an
IDENTITY
key, although the code shows thatLocationInformationId
is supplied by the application. To do this, the query will have to be modified to return any generated value, eg with theOUTPUT
clause.Returning generated values
For example, this will return the auto-generated ID :
The question's code already uses
ExecuteAsync(sql, IEnumerable<T>,...)
to insert multiple items. That executes the query once for every item but doesn't return any results. There's no equivalent forQueryAsync
, so the application will have to execute the INSERTs explicitly :Row constructors
It's possible to insert multiple rows with a single INSERT using row constructors, but that requires generating the SQL query dynamically :
All item values will have to be flattened by the application to a list of parameters too. Not very helpful.
Table valued parameters
Another option is to use a table-valued parameter type parameter to insert multiple values passed as a DataTable at once. This requires creating a table valued parameter type in the database and converting the data into a DataTable, eg :
The query should change to an
INSERT ... SELECT
using the table parameter :MoreLinq's ToDataTable can be used to convert the input items to a DataTable. After that, a
QueryAsync
call will execute the INSERT and return the list of outputs :fcg9iug32#
If I understand you correctly you want to do inserts on the table in batches. Pure Dapper does not have any built in way to do bulk inserts, so your options would be either using Dapper-Plus or SqlBulkCopy for all bulk actions you want to perform.
With SqlBulkCopy you could set up a dynamic columnmapping using reflection to avoid having to define all columns explicitly.