Bulk Insert in multiple relational tables using Dapper .Net-using scope identity




I need to import millions of records in multiple sql server relational tables.



```
TableA(Aid(pk),Name,Color)return id using scope identity 
TableB(Bid,Aid(fk),Name)Here we need to insert Aid(pk) which we got using scocpe Identity

```

How I can do bulk insert of collection of millions of records using dapper in one single Insert statement
Dapper just wraps raw ADO.NET; raw ADO.NET doesn't offer a facility for this, therefore dapper does not. What you want is `SqlBulkCopy`. You could *also* use a table-valued-parameter, but this really feels like a `SqlBulkCopy` job.


In a pinch, you can *use* dapper here - `Execute` will unroll an `IEnumerable<T>` into a series of commands about `T` - but it will be lots of commands; and unless you explicitly enable async-pipelining, it will suffer from latency per-command (the pipelined mode avoids this, but it will still be n commands). But `SqlBulkCopy` will be *much* more efficient.


If the input data is an `IEnumerable<T>`, you might want to use `ObjectReader` from FastMember; for example:



```
IEnumerable<SomeType> data = ...
using(var bcp = new SqlBulkCopy(connection))
using(var reader = ObjectReader.Create(data, "Id", "Name", "Description"))
{
    bcp.DestinationTableName = "SomeTable";
    bcp.WriteToServer(reader);
}

```
you might be able to use synchronize. if you have more than 2 tables, you will need to use it multiple times. You could try using the in line view like this:


Select table1.col1, table1.col2, table1…., table2.col1, table2.col2, table2….  

 from  

(SELECT *  

FROM dbo.Shaft\_Scales  

WHERE dbo.Shaft\_Scales.ID = (SELECT max(ID) from dbo.Shaft\_Scales ID) as table1,  

(SELECT *  

FROM OtherTable  

WHERE dbo.OtherTable.ID = (SELECT max(ID) from dbo.OtherTable ID) as table2


—————- another approach from meandyou 


This works on [at least some] SQL processors


SELECT T1.* , T2.*  

FROM table1 T1, table2 T2  

WHERE …


Do we have to discuss why not to use “SELECT * ” in your SQL?<pre>


Try this


SELECT * FROM T1 as a, T2 as b WHERE a.ID = (SELECT max(ID) from T1)  

and b.ID = (SELECT max(ID) from T2);</pre> Did you bind the listBox1, using DataSource property from DataTable?  

If so, you have to 1st get the item and value from listBox item and add it some other place (in your case to listBox2):



```
for(int i = 0; i < listBox1.SelectedItems.Count; i++)
{
     DataRowView view = listBox1.SelectedItem as DataRowView;
     string item = view["ColumnNameOfItem"].ToString(); //can be some name
     int value = Convert.ToInt32(view["ColumnNameOfValue"]);  //can be some id (number)
     listBox2.Items.Add(item); // it you want to add item (you can add value as well);
}
```

ColumnNameOfItem (or OfValue) are the names of fields in your dataTable (and same are in dataBase as well). Insteads of names you can use indexes (0 and 1, but without quotation marks).



Hope it helps.  

bye wrapping the query in a sumseries() should do what you want, i.e. sumseries(collectd.$host.$volumegroups.$logicalvolumes). hi [@jitse\_b](/u/jitse_b)

welcome to the community !

yes you can, there are various ways to do so.

the simplest:

you may want to create a table with 3 columns,

key\_column, type text, value “k000” (or whatever you want, it doesn’t matter if you stick to only one comparison)

“material1”, type ref, source tabl… Here is a link to assist you.


<https://technet.microsoft.com/en-us/library/ms178078(v=sql.105).aspx>


If you had done a web search with the question you entered here, you would have found multiple sites that give you the instructions Lets say you want to send a table with a single column of GUIDs.


First we need to create a structure using [SqlMetaData](https://msdn.microsoft.com/en-us/library/microsoft.sqlserver.server.sqlmetadata(v=vs.110).aspx) which represents the schema of the table (columns).



```
var tableSchema = new List<SqlMetaData>(1)
{
  new SqlMetaData("Id", SqlDbType.UniqueIdentifier)
}.ToArray();

```

Next you create a list of records that match the schema using [SqlDataRecord](https://msdn.microsoft.com/en-us/library/microsoft.sqlserver.server.sqldatarecord(v=vs.110).aspx).



```
var tableRow = new SqlDataRecord(tableSchema);
tableRow.SetGuid(0, Guid.NewGuid());
var table = new List<SqlDataRecord>(1)
{
  tableRow
};

```

Then create the [SqlParameter](https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlparameter(v=vs.110).aspx):



```
var parameter = new SqlParameter();
parameter.SqlDbType = SqlDbType.Structured;
parameter.ParameterName = "@UserIds";
parameter.Value = table;

var parameters = new SqlParameter[1]
{
  parameter
};

```

Then simply call the stored procedure by using the [Database.SqlQuery](https://msdn.microsoft.com/en-us/library/gg696545(v=vs.113).aspx).



```
IEnumerable<ReturnType> result;
using (var myContext = new DbContext())
{
  result = myContext.Database.SqlQuery<User>("GetUsers", parameters)
    .ToList();         // calls the stored procedure
    // ToListAsync();  // Async
{

```

In SQL Server, create your User-Defined Table Type (I suffix them with TTV, Table Typed Value):



```
CREATE TYPE [dbo].[UniqueidentifiersTTV] AS TABLE(
  [Id] [uniqueidentifier] NOT NULL
)
GO

```

Then specify the type as a parameter (don't forget, Table Type Values have to be readonly!):



```
CREATE PROCEDURE [dbo].[GetUsers] (
  @UserIds [UniqueidentifiersTTV] READONLY
) AS
BEGIN
  SET NOCOUNT ON

  SELECT u.* -- Just an example :P
  FROM [dbo].[Users] u
  INNER JOIN @UserIds ids On u.Id = ids.Id
END

``` Hi Djhenry,
  

  
When you right-click a sheets tab, you can select all sheets. When you have done that, you can insert a row and enter all the information and all sheets wil contain that information.
  

  
Best regards,
  
Trowa hi stuti, 
index can be used with lists, not tables. 
if a variable is used as an index, it is put in the square brackets without the dollar sign and curly brackets, i.e. ${data\_list[item\_index]}. 
you can read more about using indexes with lists in the knowledge base: [https://kb.workfusion.com/disp…](https://kb.workfusion.com/display/rpae/recorder+variables#recordervariables-usingindexeswithlists) hi, @ricky007 
create table bill\_stag
(
s\_categry varchar2(20),
s\_billnum varchar2(20)
);

insert into bill values('1111','5647859541785');
watch out! you're using two different table names there.
you don't care which m\_billnum\_seq gets assigned to which new row, do you? (you shouldn't.) in that case, you can simplify the cross join approach that cormaco suggested like this:
insert into bill\_mast (m\_bill\_seqnum, m\_billnum, channel) -- always name the columns
with  all\_channels  as
(
 select 'mob' as channel  from dual  union all
 select 'atm'      from dual
)
select  seq\_num.nextval
, s.s\_billnum
, c.channel
from     bill\_stag    s
cross join all\_channels c
;
you don't need order by, so you don't need the ord column and you don't need so an extra sub-query.