SqlBulkCopy insert order - c#

To copy data from one database to another in different server with same schema, I am planning to use SqlBulkCopy class from C sharp library. Whether SqlBulkCopy will maintain the same order as it is in the datatable while inserting the records ?
Example: id is the identity column.
Server1, db1
TableA
id name
1 name10
2 name20
3 name30
4 name40
Server2, db1
TableA
id name
1 name1
2 name2
3 name3
4 name4
..........
..........
5000 name22
5001 name33
Step1: var dt = select * from server1.dbo.TableA order by id;
Step2: SQL bulk copy into server2 bulkCopy.WriteToServer(dt);
Step3: var resultDt = select top 4 id from server2.dbo.TableA order by id desc. Since we know the number of records we inserted I am using "top 4".
Step4: resultDt.DefaultView.Sort = "id asc";
Question: Whether id in resultDt will represent id in dt for all the rows ? i.e,.
5002 from server2 = 1 from server1
5003 from server2 = 2 from server1
5004 from server2 = 3 from server1
5005 from server2 = 4 from server1
Note: Just for example purpose I have given less records. Actual table contains some thousands of records.

It looks like there is no guarantee of order while bulk insert. So I added a temporary id column to the destination table. Flow will be as follows:
Step1: var dt = select *, id as tempId from server1.dbo.TableA order by id;
Step2: SQL bulk copy into server2 bulkCopy.WriteToServer(dt);
Step3: var resultDt = select top 4 id, tempId from server2.dbo.TableA order by id desc. Since we know the number of records we inserted I am using "top 4".
Now id will be the new id generated by server2 and tempId will be the id from server1. Problem solved :)

Another solution is available in the below link:
https://social.msdn.microsoft.com/Forums/en-US/ee3d90b0-d212-4bf0-8f2a-5dcb716896eb/sqlbulkcopy-insert-order?forum=adodotnetdataproviders
Create staging table(say tmp_tableA) with same structure of tableA
without identity.
Bulk copy the data into tmp_tableA.
Now insert into tableA from tmp_tableA.

Related

Compare two DataTables with several keys and select the rows that are not present in second table

I have two DataTables and I want to select the rows from the first one which are not present in second one, both tables have 3 Keys custnum, shiptonum, connum
For example:
Table Contacts
custnum shiptonum connum column
1 1 1 data1
2 2 2 data2
3 3 3 data3
4 4 4 data4
Table Invitations
custnum shiptonum connum column
1 1 1 data11
3 3 3 data33
I'd like the result to be:
Table Result
custnum shiptonum connum column
2 2 2 data2
4 4 4 data4
I already tried using
var differences = table1.AsEnumerable().Except(table2.AsEnumerable(),DataRowComparer.Default);
but it didn't work. For example in my testing in Contacts table I have 14,389 records, in Invitations table I have two records that exist in Contacts table the count after using the abovesolution was 14,389 instead of 14,387 (removing the two records from Invitations table).
You wrote:
I want to select the rows from the first one which are not present in second one
From your example, I see that you don't want to select rows from the first table that are not rows in the second table, but that you only want to take the values of the keys into account:
I want to select all rows from tableA which have keys with values that are not keys from tableB
You didn't define your tables. They might be IQueryable, or IEnumerable, for your LINQ statements there is not a big difference. Try to avoid AsEnumerable, especially if your data source is in a different process, like a database management system. The other process is much more efficient in executing your query than your process. AsEnumerable transports all data from your other process to your process, which is a relatively slow process. Therefore as a rule: Only use AsEnumerable this if you really need to,
The second definition defines clearer what you want: apparently from tableB you only need the keys:
var keysTableB = tableB.Select(row => new
{
CustNum = row.custNum,
ShipToNum = row.shiptonum,
ConNum = row.connum,
});
In words: from every row in tableB make one new object of anonymous type with three properties: CustNum, ShipToNum and ConNum
Select uses lazy execution. No query is executed, only property Expression is changed.
Now you want to keep only the rows from tableA that have a key that is a member of sequence keysTableB: if you want to keep a subset of a sequence, use Where
var result = tableA.Where(row => keysTableB.Contains(new
{
CustNum = row.custNum,
ShipToNum = row.shiptonum,
Connum = row.connum,
}));
In words: from every row in tableB keep only those rows that have a key that is also in keysTableB, using value equality.
TODO: consider concatenating these two LINQ statements into one.I doubt whether this would improve performance. It surely will deteriorate readability of your code, and thus decreases changeability / maintenance / testability.
for (int i=0;i<table1.rows.count;i++)
{
var rowExists = from dr in table2.AsEnumerable()
where dr.Field<typeofcolumn>("colum_name")==table1.Rows[i]["column_name"]
select dr;
if(rowExists.ToList().Count==0)
{
//here u import row table1.rows[i] to new table
}
}

Batching data from a temp table

I create a temp table, insert data (and output) and select. I need to batch them and read.
Example: If I have 110 records,and I want to read a batch of 50 records each time, then I will have read 1-50 the first time, 51-100 the second time and 100-110 the third time.
The queries are as follows
create table #mytable
{
customerID int not null
}
insert into #mytable(id)
Output inserted.CustomerID
select top 50 customerID from customer where customerID not in (select c.customerID from #mytable c)
In C#, I my code is like this
do {
getCustomerInformation() //this method does the query processing
} while(customerInfo.Any());
this query works when I run it on SQL server but not in C#. Keeps returning the first 50 rows all the time.
simple use this query ,
1) First time #PageNumber parameter will be 1 ,
2nd time will be 2 and third time send 3
DECLARE #PageNumber AS INT, #RowspPage AS INT
SET #PageNumber = 1 -- 2 , 3
SET #RowspPage = 50
SELECT customerID FROM (
SELECT ROW_NUMBER() OVER(ORDER BY id) AS Numero,
customerID FROM customer
) AS TBL
WHERE Numero BETWEEN ((#PageNumber - 1) * #RowspPage + 1) AND (#PageNumber * #RowspPage)
ORDER BY customerID
In SSMS, you have your temp table, and you check the IDs for your batch by checking the temp table.
Temp tables normally only live as long as the session. So if in C# you initialize a new session each time you call the method, your session will not see the temp table from the previous session.
You can get around this using ##two hashes, or just create an actual staging table.
There are ways ..
From SQL Server 2012, we can use OFFSET and FETCH NEXT Clause to achieve the pagination.
Try this:
2 For all version of sql post 2005 we can achieve the same with CTE and passing Param more detals
You can achieve paging in C# using the Take() and Skip() methods provided by LINQ:
const int batchSize = 50;
do {
var currentBatch = customerInfo.Take(batchSize);
customerInfo = customerInfo.Skip(batchSize);
} while(customerInfo.Any());

select two columns from two different tables in the same db using mysql + use the output of query in C#

Dear Friends,
i want to select two columns from two different tables in the same db using mysql and set the output of the query to a variable in c#.
currently my code is as shown below:
MySqlCommand logcmdCheck = new MySqlCommand(query, connectionCheck);
string query = "SELECT DB.table1.column1,DB.table1.column2,DB.table2.column1,DB.table2.column2,DB.table2.column3 FROM DB.table1 WHERE DB.table1.column1=?x,DB.table2 WHERE DB.table2.column1=?y";
logcmdCheck.Parameters.AddWithValue("?x",UserName);
logcmdCheck.Parameters.AddWithValue("?y",emailID);
MySqlDataReader ldr = logcmdCheck.ExecuteReader();
A = ldr[0].ToString();
B = ldr[1].ToString();
C = ldr[2].ToString();
D = ldr[3].ToString();
E = ldr[4].ToString();
Error: Mysql query syntax is wrong.
Kindly please help me out with the mysql command to perform the requirement.
Thanks in advance
Suraj
You're going to have to use a SQL Join. Check it out here http://www.w3schools.com/sql/sql_join.asp. You need to have a foreign key in one of the tables that allows you to connect to the primary key of the other table. Every good database should be set up with tables that have foreign keys.
For example:
Table 1:
OrderNumber Name Order Total
1 John Smith 10.00
2 Sally Smith 5.00
3 Berry Jones 25.00
Table 2:
Item Number ItemTotal OrderNumber
1 5.00 1
2 5.00 1
3 2.50 2
4 2.50 2
5 25.00 3
In table 2 the OrderNumber is the foreign key that is able to join to table one. So your syntax would be:
SELECT * FROM table1 JOIN table2 ON table2.OrderNumber = table1.OrderNumber
That will give you one table which you can read from.

Create SQLite Database From Other SQLite Database C#

I have an SQLite database which a set of tables. All data in these tables can be isolated into a groups of sets by some id. For example:
Table A
ID value1 value2
1 asd fgh
2 sdf ghj
Table B
ID ID2 value4
1 10 vbn
2 11 bnm
Table C
ID2 value5 value6
10 asdfg qwer
11 tyui hjkl
Where each ID column will map the other ID and each ID2 will map to the other ID2.
I want to take this database, and generate a series of smaller databases, each of which have the same structure, but will only contain data from 1 ID:
Database1.sqlite
Table A
ID value1 value2
1 asd fgh
Table B
ID ID2 value4
1 10 vbn
Table C
ID2 value5 value6
10 asdfg qwer
Database2.sqlite
Table A
ID value1 value2
2 sdf ghj
Table B
ID ID2 value4
2 11 bnm
Table C
ID2 value5 value6
11 tyui hjkl
I could just create the tables one by one, gather all data per ID through a series of SELECT statements, then add it through a series of INSERT statements, but I think there has to be a better way.
My other idea is that I can create a series of views, each of which isolates the data into the format above. From there, I could just write these series of views an sqlite file as a database.
My question is how realistic is my view generation idea? Would it be possible to generate a series of views that mimic each table's structure, but for say where ID = 1 and then save those views as an sqlite file? All of this will need to be done in C#. Is there a better way to do what I am trying to do?
Some More Info
These tables can have multiple rows with the same IDs. There will also need to be some primary key / foreign keys for each table. Ideally, we could then take these smaller tables, and then compress them all into a larger table in the future.
It is possible to combine INSERT and SELECT.
Together with ATTACHed databases, this allows to do the copying with one statement per table:
ATTACH 'C:\some\where\Database1.sqlite' AS db1;
CREATE TABLE db1.A(ID, value1, value2);
CREATE TABLE db1.B(ID, ID2, value4);
CREATE TABLE db1.C(ID2, value5, value6);
INSERT INTO db1.A SELECT * FROM main.A WHERE ID = 1;
INSERT INTO db1.B SELECT * FROM main.B WHERE ID = 1;
INSERT INTO db1.C SELECT * FROM main.C
WHERE ID2 IN (SELECT ID2 FROM B WHERE ID = 1);
ATTACH 'C:\some\where\Database2.sqlite' AS db2;
CREATE TABLE db2.A(ID, value1, value2);
CREATE TABLE db2.B(ID, ID2, value4);
CREATE TABLE db2.C(ID2, value5, value6);
INSERT INTO db2.A SELECT * FROM main.A WHERE ID = 2;
INSERT INTO db2.B SELECT * FROM main.B WHERE ID = 2;
INSERT INTO db2.C SELECT * FROM main.C
WHERE ID2 IN (SELECT ID2 FROM B WHERE ID = 2);

How to remove the duplicate rows by summing up the required columns in a datatable

Hi all I am having my data table which is from my database is as follows
Name Total
XYZ 20
XYZ 20
ABC 20
Now I would like to have my data table as follows
Name Total
XYZ 40
ABC 20
I tried this linq from here Find duplicate and merge record into single datatable c# which works fine but as I am having my values from database I don't know the type of the variable so can some one help me and give me the solution in non-linq way
If you have two tables and you want to combine them all then the below is what you are after
SELECT bothTables.Name, SUM(total) FROM
(
SELECT Name, SUM(total) as total FROM Table_1 GROUP BY Name
UNION ALL
SELECT Name, SUM(total) as total FROM Table_2 GROUP BY Name
) AS bothTables
GROUP BY bothTables.Name
ORDER BY bothTables.Name desc
or if you want to do it using your Data Table (dt in this example)
var summedValues = from table in dt.AsEnumerable()
group table by table.Field<string>("Name")
into groupedTable
select new
{
Name = groupedTable.Key,
Total = groupedTable.Sum(x => x.Field<int>("Total"))
};
SQL version of the solution would be:
select Name, sum(Total) group by Name

Categories