Linq to SQL bulkupdate from 2 different databases, 2 different tables - c#

Hello i'm using linq and sql to create a windows serrvice that updates some rows if there was a change in the table in the last 5 minutes so far this is what i have:
using System;
using System.Data.SqlClient;
using System.Linq;
namespace Prueba
{
internal static class Program
{
private static void Main()
{
int tienda = 9;
var conex = new DataClasses1DataContext();
try
{
var source =
new SqlConnection(
"Server=LAPTOP-VCD9V9KH\\SQLEXPRESS;Database=backoffice;User Id=sa; Password=root;");
var destination =
new SqlConnection(
"Server=LAPTOP-VCD9V9KH\\SQLEXPRESS;Database=Corporativo_PRB;User Id=sa; Password=root;");
source.Open();
destination.Open();
source.CreateCommand();
var infoExistenciases = conex.Info_Existencias.Where(x => x.FechAct > DateTime.Now.AddMinutes(-5));
foreach (var x in infoExistenciases)
{
var cmd2 = new SqlCommand(
"update Info_Corp_Existencias set Existencia =" + x.Existencia + " where sku ='" + x.SKU + "'" +
"AND Tienda =" + tienda, destination);
cmd2.ExecuteNonQuery();
}
source.Close();
destination.Close();
Console.Beep();
}
catch
(Exception e)
{
Console.WriteLine(e);
Console.ReadLine();
throw;
}
}
}
}
So far this code updates everything in the destination server but i can't really really pinpoint down how to put everything into a temp table to let linq update it foreach argument.
Thank you for your time

Since it's in two different tables, it's difficult to select the corresponding row in the second table without knowing the table design exactly. But you can probably do something like this:
var cmd2 = new SqlCommand(
"update Info_Corp_Existencias set Existencia = (select field FROM Info_Existencias WHERE id=#otherid where sku ='" + x.SKU + "'" +
"AND Tienda =" + tienda, destination);
cmd2.ExecuteNonQuery();
So leave out the foreach statement and just launch ONE update statement to the database that will update every row's field by using a subselect to get the correct value from the row.
Hope this helps.

Related

Program won't load to selected database, makes a copy in debug folder

This program is supposed to take a csv file and load it to a sqlite database that the use specifies a path to. Rather than trying to load the values to the selected database it creates a copy of the database in the debug folder and then throws an error because the table doesn't exist in the new db. I can't find where it's deciding to make a new file rather than using the existing one.
using (System.Data.SQLite.SQLiteConnection conn = new System.Data.SQLite.SQLiteConnection("data source=" + db3FilePath + "; Synchronous=Off"))
{
using (System.Data.SQLite.SQLiteCommand cmd = new System.Data.SQLite.SQLiteCommand(conn))
{
conn.Open();
foreach (KeyValuePair<string, CSVRecord> kvp in csvDictionary.Skip(1))
{
//checks for duplicate records
cmd.CommandText = "SELECT COUNT(*) FROM Accounts WHERE SDM_ACCT='" + kvp.Value.sdmacct + "'";
int count = Convert.ToInt32(cmd.ExecuteScalar());
if (count < 1)
{
WritetoDatabase.WritetoAccountsTable(kvp.Value.description, kvp.Value.priority, db3FilePath);
WritetoDatabase.WritetoDirectoryTable(kvp.Value.number, kvp.Value.active, db3FilePath);
recordCount++;
//updates the progress bar and text field showing %
int progress = y++ * 100 / (csvDictionary.Keys.Count -1);
progressBar1.Invoke((MethodInvoker)(() => progressBar1.Value = progress));
progressBar1.Invoke((MethodInvoker)(() => progressBar1.Update()));
lblStatus.Invoke((MethodInvoker)(() => lblStatus.Text = "Writing records to database: " + progress.ToString() + "% Complete"));
lblStatus.Invoke((MethodInvoker)(() => lblStatus.Update()));
}
else
{
WritetoDatabase.WritetoDirectoryTable(kvp.Value.number, kvp.Value.active, db3FilePath);
y++;
}
}
conn.Close();
}
}
Here is a copy of the method that writes to the database.
public static int WritetoAccountsTable(string Comment, int PriorityInt, string filePath)
{
using (System.Data.SQLite.SQLiteConnection conn = new System.Data.SQLite.SQLiteConnection("data source=" + filePath + "; Synchronous=Off"))
{
using (System.Data.SQLite.SQLiteCommand cmd = new System.Data.SQLite.SQLiteCommand(conn))
{
conn.Open();
cmd.CommandText = #"INSERT INTO Accounts(Description,Priority)
values(#Comment,#PriorityInt)";
cmd.Parameters.AddWithValue("#Comment", Comment);
cmd.Parameters.AddWithValue("#PriorityInt", PriorityInt);
return cmd.ExecuteNonQuery();
}
}
}
I've changed everything I can think of trying to find what's causing the problem. Maybe you will see something I can't.
One of the all-time dumbest things I have seen break a program. The Connection String using (System.Data.SQLite.SQLiteConnection conn = new System.Data.SQLite.SQLiteConnection("data source=" + filePath + "; Synchronous=Off")) has "data source". If it is not capitalized, "Data Source", it doesn't recognize it and goes to a default setting.

Show data in Textboxes from database in C#

Is there anything wrong with my code? It is not showing data in textboxes. The same funtion is working for another table in database but not for this one.
private void metroButton1_Click(object sender, EventArgs e)
{
con = new SqlConnection(constr);
String query = "Select FROM Student WHERE Std_ID = '" + metroTextBox1.Text + "'";
cmd = new SqlCommand(query, con);
con.Open();
try
{
using (SqlDataReader read = cmd.ExecuteReader())
{
while (read.Read())
{
// metroTextBox1.Text = (read["ID"].ToString());
metroTextBox2.Text = (read["Name"].ToString());
metroTextBox3.Text = (read["F_Name"].ToString());
metroTextBox4.Text = (read["Std_Age"].ToString());
metroTextBox5.Text = (read["Address"].ToString());
metroTextBox6.Text = (read["Program"].ToString());
metroComboBox1.Text = (read["Course"].ToString());
}
}
}
finally
{
con.Close();
}
}
you need to give column names in the select statement or select *
for example :
String query = "Select * from Student WHERE Std_ID = '" + metroTextBox1.Text + "'";
Not related to Question: you can change the while loop to if condition if you have one record for given id. even there are many records for given id you will see the last record data only because of the while loop will overwrite the textboxes in every record.
Update :
There isn't anything wrong with Syntax because the same syntax is
working for modifying teacher funtion.
No, this is incorrect, remove the try catch in your code then you will see the exception of syntax error

How to use Linq instead of SQL Injection query for custom search

I would like to use Linq instead of below hardcoded Sql Injection to search from SqlServer DATABASE TABLES. How to retrieve Dynamically generated web controls input texts in C# Linq and replace the entire Sql injection in Linq for searching.
My C# code:
protected void Search_Button_Click(object sender, EventArgs e)
{
try
{
Table maintable = Select.FindControl("dynamic_filter_table_id") as Table;
int rc = maintable.Rows.Count;
if (rc == 1)
{
DropDownList D1 = maintable.FindControl("MainDDL") as DropDownList;
if (D1.SelectedValue.Contains("decimal"))
{
TextBox T1 = maintable.FindControl("txtbox1") as TextBox;
TextBox T2 = maintable.FindControl("txtbox2") as TextBox;
SqlDataAdapter sql = new SqlDataAdapter("SELECT F.Col1,F.Col2,V.COL1, col2,col3, col4 , col5, cl6 FROM TABLE1 as V , TABL2 as F WHERE V.Col1 = F.Col1 AND " + DDL1.SelectedItem.Text + " >= " + T1.Text + " AND " + DDl1.SelectedItem.Text + " <= " + T2.Text, con);
DataSet data = new DataSet();
sql.Fill(data);
con.Close();
Session["DataforSearch_DDL"] = data.Tables[0];
}
}
}
catch
{
ImproperSearch();
}
}
Why don't you just rewrite your query to be SQL-injection safe? LINQ won't give you any benefit.
You can achieve that by doing two things.
The first is to secure the column names. That is accomplished by specifying which characters is allowed for column names (more secure than trying to figure out what characters is not allowed). In this case I remove everything but letters and digits. If you have column names which contains underscore, just add that to the check.
The next thing is to use parameterized queries. Each ADO.NET driver has built in support for that, so you just have to specify the value using cmd.Parameters.AddWithValue. By doing so the value isn't part of the query string and hence there is no potential SQL injection.
using (var con = yourConnectionFactory.Create())
{
using (var cmd = new SqlCommand(con))
{
var safeKey1 = OnlyLettersAndDigits(DDL1.SelectedItem.Text);
var safeKey2 = OnlyLettersAndDigits(DDL2.SelectedItem.Text);
cmd.CommandText = "SELECT F.Col1,F.Col2,V.COL1, col2,col3, col4 , col5, cl6 " +
" FROM TABLE1 as V , TABL2 as F WHERE V.Col1 = F.Col1 " +
" AND " + safeKey1 + " >= #text1 " +
" AND " + safeKey2 + " <= #text2 ";
cmd.Parameters.AddWithValue("text1", T1.Text);
cmd.Parameters.AddWithValue("text2", T2.Text);
var adapter = new SqlDataAdapter(cmd);
var data = new DataSet();
sql.Fill(data);
Session["DataforSearch_DDL"] = data.Tables[0];
}
}
public string OnlyLettersAndDigits(string value)
{
var stripped = "";
foreach (var ch in value)
{
if (char.IsLetterOrDigit(ch))
stripped += ch;
}
return stripped;
}
You can use store procedure for customer search, It will work for both ADO.Net and LINQ approach. Just create a SP and add it to your DBML file very simple.
Here is the link how you can use SP in LINQ
http://www.mssqltips.com/sqlservertip/1542/using-stored-procedures-with-linq-to-sql/

MS Access Oledb column properties

And I solved this problem in VBA using DAO here
Using the Oledb framework, I created a function that can look up a record value. However it only gets the raw value. I need to find the value of the column property called "Row Source"
Can someone explain to me how to find the foreign key value using Oledb
Below is my function for a traditional look up query.
string IDatabase.LookupRecord(string column, string table, string lookupColumn, string lookUpValue)
{
OleDbCommand cmdLookupColumnValue = new OleDbCommand();
string sqlQuery = "SELECT [" + table + "].[" + column + "] " +
"FROM [" + table + "] " +
"WHERE [" + table + "].[" + lookupColumn + "] = '" + lookUpValue + "'";
cmdLookupColumnValue.CommandText = sqlQuery;
cmdLookupColumnValue.CommandType = CommandType.Text;
cmdLookupColumnValue.Connection = connection;
string result = "";
try
{
result = cmdLookupColumnValue.ExecuteScalar().ToString();
}
catch(Exception ex)
{
MessageBox.Show("Query is not valid :" + ex.ToString());
}
return result;
}
EDIT I found the following code here Its the closest Ive gotten so far. It does get column properties like the column Description but it doesnt work for row Source. Any Ideas?
public void Test()
{
string columnName = "Main Space Category";
ADOX.Catalog cat = new ADOX.Catalog();
ADODB.Connection conn = new ADODB.Connection();
conn.Open(connectionString, null, null, 0);
cat.ActiveConnection = conn;
ADOX.Table mhs = cat.Tables["FI - ROOM"];
var columnDescription = mhs.Columns[columnName].Properties["Description"].Value.ToString();
MessageBox.Show(columnDescription);
conn.Close();
}
I strongly suspect that the RowSource property of a table column is so specific to Access that you will have to use DAO to retrieve it. The following C# code is an example of how you might do that:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace daoConsoleApp
{
class Program
{
static void Main(string[] args)
{
string TableName = "Cars";
string FieldName = "CarType";
// This code requires the following COM reference in your project:
//
// Microsoft Office 14.0 Access Database Engine Object Library
//
var dbe = new Microsoft.Office.Interop.Access.Dao.DBEngine();
Microsoft.Office.Interop.Access.Dao.Database db = dbe.OpenDatabase(#"Z:\_xfer\Database1.accdb");
try
{
Microsoft.Office.Interop.Access.Dao.Field fld = db.TableDefs[TableName].Fields[FieldName];
string RowSource = "";
try
{
RowSource = fld.Properties["RowSource"].Value;
}
catch
{
// do nothing - RowSource will remain an empty string
}
if (RowSource.Length == 0)
{
Console.WriteLine("The field is not a lookup field.");
}
else
{
Console.WriteLine(RowSource);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}

how to reference columns in sql server connection in C#

I'm trying to translate some perl code into C# and I'm having some trouble with the following.
After establishing a sql server connection and executing the select statement, how do I reference the different elements in the table columns. For example, in Perl it looks like:
my $dbh = DBI -> connect( NAME, USR, PWD )
or die "Failed to connect to database: " . DBI->message;
my $dbname = DB_NAME;
my $dbschema = DB_SCHEMA;
my $sql = qq{select a,b,c,d,e,f,g,h,i,...
from $dbname.$dbschema.package p
join $dbname.$dbschema.package_download pd on p.package_id = pd.package_id
join $dbname.$dbschema.download d on pd.download_id = d.download_id
where p.package_name = '$package'
--and ds.server_address like 'tcp/ip'
order by a,b,c,d,..};
my $sth = $dbh -> prepare( $sql )
or die "Failed to prepare statement: " . $dbh->message;
$sth -> execute()
or die "Failed to execute statement: " . $sth->message;
#now to go through each row in result table
while ( #data = $sth->fetchrow_array() )
{
print "$data[0]";
# If source server FTP is not already open, make new FTP
if ( $data[0] != $src_id )
{
if ( $src_ftp )
{ $src_ftp -> quit; }
$src_ftp = make_ftp( $data[1], $data[2], $data[3], $data[18], $data[19], $data[20] );
$src_id = $data[0];
}
}
so far I've got it down to
string db = NAME;
string myConnectionString = "Data Source=ServerName;" + "Initial Catalog=" + db + "User id=" + ODBC_USR + "Password=" + PWD
SqlConnection myConnection = new SqlConnection(myConnectionString);
string myInsertQuery = "select a,b,c,d,e,f,g,h,i,...
from $dbname.$dbschema.package p
join $dbname.$dbschema.package_download pd on p.package_id = pd.package_id
join $dbname.$dbschema.download d on pd.download_id = d.download_id
where p.package_name = '$package'
--and ds.server_address like 'tcp/ip'
order by a,b,c,d,..";
SqlCommand myCommand = new SqlCommand(myInsertQuery);
myCommand.Connection = myConnection;
myConnection.Open();
myCommand.ExecuteNonQuery();
myCommand.Connection.Close();
but how do I reference the columns like data[0] and data[1] in C#. Sorry I'm new to both languages so my background is severely lacking. Thanks!
You could reference your column directly by its column name or by numeric order (it starts with 0 as the first column) either through a DataTable, DataSet, DataReader or a specific DataRow.
For the sake of example i'll use a DataTable here and I will name it as dt and let's say we want to reference the first row then you could reference it with the following Syntax/Format:
dt[RowNumber]["ColumnName or Column Number"].ToString();
For example:
dt[0]["a"].ToString();
Or by number the first column with be 0 like:
dt[0][0].ToString();
And use Parameters by the way because without which it would be susceptible to SQL Injection. Here's a more complete code below:
string db = NAME;
string myConnectionString = "Data Source=ServerName;" + "Initial Catalog=" + db + "User id=" + ODBC_USR + "Password=" + PWD
using (SqlConnection connection = new SqlConnection(myConnectionString))
{
string mySelectQuery = #"SELECT a,b,c,d,e,f,g,h,i,...
FROM package p
JOIN package_download pd on p.package_id = pd.package_id
join download d on pd.download_id = d.download_id
WHERE p.package_name = #PackageName
AND ds.server_address LIKE 'tcp/ip%'
ORDER by a,b,c,d";
try
{
connection.Open();
using (SqlDataAdapter da = new SqlDataAdapter(mySelectQuery, connection))
{
using (SqlCommand cmd = new SqlCommand())
{
da.SelectCommand.Parameters.AddWithValue("#PackageName", txtPackage.Text);
DataTable dt = new DataTable();
da.Fill(dt);
if (dt.Rows.Count>0) // Make sure there is something in your DataTable
{
String aVal = dt[0]["a"].ToString();
String bVal = dt[0]["b"].ToString();
// You'll be the one to fill up
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I change your LIKE 'tcp/ip' to LIKE 'tcp/ip%' by the way which is the more appropriate one of using LIKE.
you can use ado.net entity data table to reference the tables in your sql server. I don't know if you're asking exactly this but it may help. because direct referencing to sql server is not possible as far as i know.

Categories

Resources