What is the best way to generate an "UPSERT" Merge statement for SQL Server? I'm looking for a way to just put in a SQL Server connection string and then point a piece of code at a single SQL Server table.
Is it to crawl INFORMATION_SCHEMA.COLUMNS and INFORMATION_SCHEMA.TABLES for the metadata and write a small console app? other suggestions?
I'd like to be able to copy and paste the resulting code into a "const string sql" variable to then use with something like Dapper.
The fastest way to upsert in SQL Server in C# is to bulk insert into a temp table and issue a merge from there to the production table.
var tmpTable =
"create table #myTable (a as int, b as nvarchar(200)";
var conString = "my_connection_string";
using (var con = new SqlConnection(conString))
{
con.Open();
//Create Temp Table
var cmd = new SqlCommand(tmpTable, con);
cmd.ExecuteNonQuery();
//Build Data Set
var dt = new DataTable();
dt.Columns.Add(new DataColumn("A", typeof(int)));
dt.Columns.Add(new DataColumn("B", typeof(string)));
foreach (var myDataRow in myData)
{
var row = dt.NewRow();
row["A"] = myDataRow.A;
row["B"] = myDataRow.B;
dt.Rows.Add(row);
}
//Write to temp table
using (var bulk = new SqlBulkCopy(con))
{
bulk.BulkCopyTimeout = 0;
bulk.DestinationTableName = "#myTable";
bulk.WriteToServer(dt);
}
//Do the upsert
var mergeSql = "merge into myData as Target " +
"using #myTable as Source " +
"on " +
"Target.A=Source.A " +
"and Target.B = Source.B " +
"when matched then " +
"update set Target.A=Source.A, Target.B = Source.B, " +
"when not matched then " +
"insert (A,B) values (Source.A,Source.B);";
cmd.CommandTimeout = 0;
cmd.CommandText = mergeSql;
cmd.ExecuteNonQuery();
//Clean up the temp table
cmd.CommandText = "drop table #myTable";
cmd.ExecuteNonQuery();
}
}
I've tested several ways and this is the fastest I have came across. I use it in a production environment for inserting millions of rows daily without issue.
Related
I have used schema for tables for one database,so how to copy all schema from one database to other database(database created at runtime)
string sql = "create database " + str1;
SqlCommand command = new SqlCommand(sql, connection);
connection.Open();
command.ExecuteNonQuery();
Response.Write("database created");
connection.Close();
string sqll = "(select * into " + str1 + ".cost_category.cost_category_info
from ERPAccounting.cost_category.cost_category_info where 1=2)
(select * into " + str1 + ".dbo.cost_centre_info from
ERPAccounting.cost_centre.cost_centre_info where 1=2)"
connection.Open();
SqlDataAdapter ad = new SqlDataAdapter(sqll, connection);
DataSet ds = new DataSet();
ad.Fill(ds);
Using C#, object DDL can be obtained by using SMO objects and then executed in the database where the objects need to be copied to. In the example below, references to Microsoft.SqlServer.Management.Smo, Microsoft.SqlServer.ConnectionInfo, Microsoft.SqlServer.Management.Sdk.Sfc, and System.Data.SqlClient are necessary. The DDL is first obtained from the SMO objects, then it used as the CommandText for the SqlCommand that is executed in the destination database. This example is for tables, but other objects (views, stored procedures, etc.) can also be copied using this method.
//set initial catalog to destination database
string connStr = #"Data Source=YourServer;Initial Catalog=DestinationDatabase;Integrated Security=SSPI;";
using (SqlConnection conn = new SqlConnection(connStr))
{
//set source server and database using SMO objects
Server srv = new Server(#"YourServer");
srv.ConnectionContext.LoginSecure = true;
srv.ConnectionContext.StatementTimeout = 600;
Database db = srv.Databases["SourceDatabase"];
//configure Scripter for DDL
Scripter script = new Scripter(srv);
ScriptingOptions scriptOpt = new ScriptingOptions();
//SQL command to execute DDL in destination database
SqlCommand sql = new SqlCommand();
sql.Connection = conn;
conn.Open();
//this can changed to views, SPs, etc. as needed
foreach (Table t in db.Tables)
{
//check for system objects
if (!t.IsSystemObject)
{
StringCollection sc = t.Script(scriptOpt);
foreach (string s in sc)
{
//assign and execute DDL
sql.CommandText = s;
sql.ExecuteNonQuery();
}
}
}
}
Can you please provide an answer following sql query to linq . I have some knowledge about linq but i am confused about sql reader object ..
public AccountBalanceRequest AccountBalanceCheek(AccountBalanceRequest accountNumber)
{
using (SqlConnection conn = new SqlConnection(ConnectionString))
{
conn.Open();
var cmd = new SqlCommand("SELECT Account_Type,Account_Fees,Account_Balance,Over_Draft_Limit FROM Current_Account_Details WHERE Account_Number = '" + accountNumber.Account_Number + "'", conn);
cmd.CommandType = CommandType.Text;
var reader = cmd.ExecuteReader();
//read the result of the execute command.
while (reader.Read())
{
//assuming that your property is the same as your table schema. refer to your table schema Current_Account_Details
accountNumber.Account_Type = reader["Account_Type"].ToString();
accountNumber.Account_Fee = reader["Account_Fees"].ToString();
accountNumber.Account_Balance = reader["Account_Balance"].ToString();
accountNumber.Over_Draft_Limit = reader["Over_Draft_Limit"].ToString();
}
return accountNumber;
}
}
First you have to have DbContext which you must instantiate in using(usual practice):
using (DbContext db = new DbContext())
{
var results = (from ad in db.Current_Account_Details
where ad.Account_Number == accountNumber.Account_Number
select ad).ToList();
}
Make sure you have created the object data model from database.
I do not get the other part of your post but this would be the general idea of how to write Linq2Entities queries.
I have three columns in Excel sheet such as id, name, family.
I am using LINQ and i need to import data from Excel to database with coding instruction, i have 6500 records in Excel sheet
You can use below code to get all the data and then you can convert form DataTable to List. for below example to work you have Microsoft Access Database Engine 2010 Redistributable
should be installed
public static DataTable ReadExcelWithoutOffice(string filePath)
{
var connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Extended Properties=\"Excel 12.0;IMEX=1;HDR=YES;TypeGuessRows=0;FirstRowHasNames=true;ImportMixedTypes=Text\""; ;
using (var conn = new OleDbConnection(connectionString))
{
conn.Open();
var sheets = conn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT * FROM [" + sheets.Rows[0]["TABLE_NAME"].ToString() + "] ";
var adapter = new OleDbDataAdapter(cmd);
var ds = new DataSet();
adapter.Fill(ds);
return ds.Tables[0];
}
}
}
Thank you all for your answer.
I found my problem. Here is the code :
string pach = #"D:\C# Projects\ex.xlsx";
var excelData = new ExcelQueryFactory(pach);
var data = from x in excelData.Worksheet<xlsdata>("MySheet")
select x;
DataClassesDataContext db = new DataClassesDataContext();
foreach (var d in data)
{
db.tbl_infos.InsertOnSubmit(new tbl_info
{
id = d.id,
name = d.name,
family = d.family
});
}
db.SubmitChanges();
You will need to import and reference OpenXML, open the sheets, sheet, worksheet, IIRC - then parse through your columns into strings.
OpenXML
Then create a SQL Data Adapter and all of that, to use either a ConnectionString or SQLConnection, fire up a parameterized query, and it's in the database.
SQL Example
In C# Visual Studio Express Windows Forms:
How do I retrieve the primary key of a just executed insert query.
Here is my con+query code:
SqlConnection con = new SqlConnection(...);
SqlCommand command = con.CreateCommand();
command.CommandText = "INSERT INTO bestillinger (ha) VALUES (#ha);
command.Parameters.AddWithValue("#ha", listBox1.SelectedItem.ToString());
con.Open();
command.ExecuteNonQuery();
con.Close();
With a manual Close(), you risk leaking a connection if the code that uses it throws an exception. So please use using instead.
Assuming your PK is an identity column, the new value is most easily retrieved with scope_identity():
using (var con = new SqlConnection(...))
{
con.Open();
var command = con.CreateCommand();
command.CommandText = #"
INSERT INTO bestillinger (ha) VALUES (#ha);
select scope_identity();";
command.Parameters.AddWithValue("#ha", listBox1.SelectedItem.ToString());
var newPk = (long) command.ExecuteScalar();
}
As #Andomar said in his answer, ensure you properly close the connection.
Another way to return the value of the newly inserted identity field would be:
using (var con = new SqlConnection(...))
{
con.Open();
var command = con.CreateCommand();
command.CommandText = #"
INSERT INTO bestillinger (ha) OUTPUT inserted.[ID] VALUES (#ha);";
command.Parameters.AddWithValue("#ha", listBox1.SelectedItem.ToString());
var newPk = (long) command.ExecuteScalar();
}
[ID] would be replaced with the name of the identity field (or any field, or fields) that you want.
I have the following code
string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + txtFileLocation.Text;
using (DbConnection conn = new OleDbConnection(connectionString))
{
conn.Open();
DbCommand command = conn.CreateCommand();
string idfield = txtIDField.Text;
string picfield = txtPictureField.Text;
command.CommandText = "select " + idfield + ", " + picfield + " from " + selectedTable;
command.CommandType = CommandType.Text;
DbDataReader reader = command.ExecuteReader();
gridResults.DataSource = reader;
conn.Close();
}
The database is an access database as u might have seen from the connection string, also the database I was provided with store their images in the database, as Image attachment.
Whenever I load the grid it shows random stuff :(
eg.
I am not familiar with the wiring up of a database so this might be an easy question, how do I enable my picture list in my form?