Join Dataset with sql db table - c#

I need to execute a query like as given below which contain a dataset in it.
UPDATE <OrderDataset>
SET FKProduct = P.PKProduct
FROM <OrderDataset> DS
INNER JOIN tblCustomer C ON DS.FKCustomer = C.PKCustomer
INNER JOIN tblProduct P ON C.PKCustomer = P.FKCustomer
INNER JOIN tblStock S ON S.FKProduct = P.PKProduct
AND DS.RotationNumber = S.RotationNumber
AND ISNULL(DS.RotationLineNo,'NULL') = ISNULL(S.RotationLineNo,'NULL')
WHERE DS.FKProduct IS NULL
Is there any way to implemnt this.

There is no direct way to do this.
You can pass the table inside the dataset as a parameter to sql server stored procedure ans then do the jon in sp. .
how to pass data table as parameter to sp

Related

C# SqlCommandBuilder , CommandUpdate - how to write correct update based on select with outer join tables

I want is to update 2 fields: p.FlagaWaznosci and p.Notatka
My select looks like:
Select DISTINCT p.id,p.Model_Number,p.Product_Name,p.Website_Link,p.Entry_date,p.LastUpdate_date,p.PrzydzialRozmiarow_ID,p.FlagaWaznosci,p.Notatka,pr.NazwaRozmiarowki,wd.LINK_StockX
from Products p with(nolock)
left outer join Widok_Model_Sklep_Stockx_Linki wd with(nolock) on wd.Product_ID = p.id
left outer join PrzydzialRozmiarow pr with(nolock) on pr.id = p.PrzydzialRozmiarow_ID
inner join Shops s with(nolock) on s.ID = p.Shop_ID
There is just outer joins to get correct data that I need to be displayed in gridview. And now when values p.FlagaWaznosci or p.Notatka is changed I want to save update in my database.
I try to use
//loads dataand fill to gridview
DataTable WszystkieProduktyDlaDanegoSklepu;
SqlDataAdapter sda555123 = new SqlDataAdapter("here is my select", conn123);
sda555123.Fill(WszystkieProduktyDlaDanegoSklepu);
//later update table Prooducts and save changed on p.Notatka and p.FlagaWaznosci
cmdbl = new SqlCommandBuilder(sda555123);
cmdbl.ConflictOption = ConflictOption.OverwriteChanges;
sda555123.Update(WszystkieProduktyDlaDanegoSklepu);
But this way I have error
So I searched a lot and found: I have to write own CommandUpdate.
So ... sda555123.UpdateCommand and I don't have idea how can I write own update for it in update command.
The update in SQL Server should looks like:
Update Products
set FlagaWaznosci = #Flagawaznosci from my sda555123,
Notatka = #Notatka from my sda555123
where id = # p.ID from my sda555123
How my command update should looks like here?
EDIT 1 :
i try added : WszystkieProduktyDlaDanegoSklepu.PrimaryKey = new DataColumn[] { WszystkieProduktyDlaDanegoSklepu.Columns["id"] }
but nothing . Still this error.
I would solve the problem by changing the approach instead of mutating the update command of the SqlDataAdapter.
Given that Products.id in your query is unique within the result set:
1- Create a temporary table (local or global), having its columns same as the result of the query with id as primary key.
2- Insert data into the temporary table using your select statement.
3- DataAdatper.selectQuery.commandText is set to "select * from TempTable"
4- The update command is now based on a simple select statement, consequently any change in the datagridview/datatable can be updated to the temptable using dataadapter.update(datatable)
5- As for the final database update, you could use the below statement
Update Prd
set Prd.FlagaWaznosci = TempTable.FlagaWaznosci ,Prd.Notatka = TempTable.Notatka etc.. all the fields that need to be updated
from my Products as Prd
Inner Join TempTable on TempTable.id = Prd.id
Note that the update in (5) will affect all rows, even unchanged ones.
To address this issue you can proceed as below
1- Save changed ids in a list.
List<string> lst = new List<string>();
foreach(DataRow dr in datatable.GetChanges(DataRowState.Modified))
{
lst.add(dr["id"].ToString());
}
2- Convert your list to a string value to be concatenated with the query in (5)
String strchange = String.Join(",",lst); //will give you id1,id2,...
//The update query becomes
Update Prd
set Prd.FlagaWaznosci = TempTable.FlagaWaznosci ,Prd.Notatka =
TempTable.Notatka etc.. all the fields that need to be updated
from my Products as Prd
Inner Join TempTable on TempTable.id = Prd.id
Where Prd.id In ( strchange )
Kindly update your tables separately because in join you just seen two or more than two tables into one table form . but you cant do any crud operation on

Use local variables and multi query command with mysql and C#

I am trying to use a two line query to a mysql database like this with C#:
set #var = 1; select id from table where id = #var`;
Executing this in C# does not give any error, the reader has columns, but don't have rows in it, so, no data is retrieved.
Running the same queries in the workbench retrieve the expected data.
Running one query to calculate the variable and other to use it replaced works.
I want to use a variable to store references and use it to filter queries that provide an union.
SET #my_value = (select min(id) from (select id from datatable limit 2000) as a);
and a complex select query, that i can resume in:
select * from
datatable as a
left join (
(select databalt2 where id > #my_value) as ba union
(select datatable3 where id > #my_value) as bb) as b
on a.id = b.id
where a.id > #my_value;
The datareader should obtain the results, but instead reports that it has no rows, but has the correct amount of columns.
And, obviously, shows no results, where it should.
Edit 1: C# code
string query = #"
SET #`my_value` = (select min(id) from (select id from datatable limit 2000) as a);
select * from
datatable as a
left join (
(select databalt2 where id > #`my_value`) as ba union
(select datatable3 where id > #`my_value`) as bb) as b
on a.id = b.id
where a.id > #`my_value`;
";
try
{
MySqlCommand command = Connection.CreateCommand();
MySqlDataReader reader;
command.CommandTimeout = commandTimeout;
command.CommandText = query;
reader = command.ExecuteReader();
}
catch (Exception ex)
{
}
These queries using local variables are possible, the local variable has to be inside like #`var`, because it can be identifyied as a local parameter.
I was missing a in a local variable call. So ... a problem between the screen and the chair!

C# Dynamic full outer join on 2 datatables

I need to do a full outer join on 2 datatables dinamically, I don't know what columns are in the datatables but they will be the same in each table, I also only have the name of the column I need to do the join on in a variable. Is there a way of doing this?
What I need to do is join 2 datatables in a C# script. I'm using a Dataflow in an SSIS to get data from a couple of files, and at the end I need to compare the 2 final sets of data. I need to to this on whatever 2 datatables as long as they have the same columns, so I can't finish the process in an SSIS as I need to specify the columns.
The GetData() I just use it in case I need to compare 2 tables but donnesPROD and donnesDEV are filled from object variables in the SSIS.
Here's my code so far :
DataTable donnesPROD = GetData(connectionPROD, sql_request);
DataTable donnesDEV = GetData(connectionDEV, sql_request);
Here's the code for GetData :
DataTable GetData(string cs, string query)
{
OleDbConnection conn = new OleDbConnection(cs);
conn.Open();
OleDbCommand cmd = new OleDbCommand(query, conn);
DataTable dt = new DataTable();
dt.Load(cmd.ExecuteReader());
conn.Close();
return dt;
}
I have the list of the columns in another datatable, and I have the name of the primary key in a string variable key. From here I need to be able to do a fullouterjoin of donnesPROD and donnesDEV on key. Can this be done this way? Or is there a way of generating the script code it self dynamically and then execute it?
You have two options.
Conditional joins
If you don't know the specific column name, but you do have some idea what the column name might be, you could do a conditional join like this:
CREATE PROCEDURE ExampleDynamicJoin(#JoinColumn AS VarChar(40))
AS
BEGIN
SELECT *
FROM TableA
JOIN TableB ON (#JoinColumn = 'ColumnA' AND TableA.ColumnA = TableB.ColumnA)
OR (#JoinColumn = 'ColumnB' AND TableA.ColumnB = TableB.ColumnB)
OR (#JoinColumn = 'ColumnC' AND TableA.ColumnC = TableB.ColumnC)
END
You may not get the best performance out of this (the conditional joins will confuse the query engine and it may not pick the best index, if it picks one at all). If the table is very large you could also do something like this. It is a bit painful-looking but will get better performance:
CREATE PROCEDURE ExampleDynamicJoin(#JoinColumn AS VarChar(40))
AS
BEGIN
IF (#JoinColumn = 'ColumnA') BEGIN
SELECT *
FROM TableA
JOIN TableB ON TableA.ColumnA = TableB.ColumnA
END
IF (#JoinColumn = 'ColumnB') BEGIN
SELECT *
FROM TableA
JOIN TableB ON TableA.ColumnB = TableB.ColumnB
END
IF (#JoinColumn = 'ColumnC') BEGIN
SELECT *
FROM TableA
JOIN TableB ON TableA.ColumnC = TableB.ColumnC
END
END
If TableA or TableA are part of a larger query, and you'd end up duplicating tons of SQL, you could always extract the resultset for just TableA and TableB into a temporary table, then use the temporary table in the larger query.
Dynamic SQL
If you don't have the foggiest about the column name and there are tons of possibilities, you could construct the SQL as a string and join that way. You should validate the column name that is passed in; not only will that make sure the column actually exists, but it will prevent the dynamic SQL from being constructed when #JoinColumn contains an injection attack, since legal column names do not contain SQL statements. Example:
CREATE PROCEDURE ExampleDynamicJoin(#JoinColumn AS VarChar(40))
AS
BEGIN
DECLARE #Sql AS VarChar(MAX)
IF NOT EXISTS
(
SELECT 0
FROM syscolumns c
JOIN sysobjects o ON o.id = c.id
WHERE o.Name = 'TableA'
AND c.Name = #JoinColumn
)
RAISERROR (15600,-1,-1, 'ExampleDynamicJoin'); //Throw error if column doesn't exist
SET #Sql =
'SELECT *
FROM TableA
JOIN TableB ON TableA.' + #JoinColumn + ' = TableB.' + #JoinColumn
sp_ExecuteSql #Sql
END
Or, if you don't use stored procedures,
DataTable ExampleDynamicJoin(string joinColumn)
{
if (!ValidateColumn(joinColumn)) throw new ArgumentException();
var sql = String.Format(
#"SELECT *
FROM TableA
JOIN TableB ON TableA.{0} = TableB.{0}",
joinColumn
);
using (var connection = GetConnectionFromSomewhere())
{
using (var cmd = new SqlCommand
{
CommandText = sql,
CommandType = CommandType.Text,
Connection = connection
})
{
var reader = cmd.ExecuteReader();
var table = new DataTable();
table.Load(reader);
return table;
}
}
}
When using dynamic SQL you should always use parameters if possible. But you can't use parameters as a column name, so in this case you have to concatenate. When concatenating, ALWAYS white list the inputs. That is why I included a function named ValidateColumn which could look like this:
bool ValidateColumn(string columnName)
{
switch columnName.ToUpper()
{
case "COLUMNA":
case "COLUMNB":
case "COLUMNC":
return true;
default:
return false;
}
}

Subquery returned more than 1 value.. query C# exception

i made a simple query joining two tables in the database using inner join. the query is given as follows:
Select t1.UserName,t1.Title,t1.FirstName,t1.LastName,t1.MiddleName,t1.IsActive,t1.ProgramID,t2.Email
from table1 t1
inner join table2 t2 on t1.UserId = t2.UserId
the query executes well in SQL Server Management Studio and returns rows as needed but while debugging my code in Visual Studio, when it reaches at
adapter.fill(dataset);
it throws the following exception:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
here is the C# code snippet:
string selectCmd = #"Select t1.UserName,t1.Title,t1.FirstName,t1.LastName,t1.MiddleName,t1.IsActive,t1.ProgramID,t2.Email
from table1 t1
inner join table2 t2 on t1.UserId = t2.UserId ";
DataSet dataset = new DataSet();
using (SqlConnection conn = new SqlConnection(MyConnString))
{
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = new SqlCommand(selectCmd, conn);
conn.Open();
adapter.Fill(dataset);
}
Any suggestions please?? Any help would be greatly appreciated.
Your join returning more than one value and you're trying to put these values in a single parameter..
Example: ----It's your error query
DECLARE #Test INT
SET #Test = (SELECT ID FROM ABC A INNER JOIN XYZ X ON A.ID = X.AID)
Solution:
DECLARE #Test INT
SET #Test = (SELECT TOP 1 ID FROM ABC A INNER JOIN XYZ X ON A.ID = X.AID)
ok guys it was a timer job issue. one has to restart the sharepoint timer service before deploying the solution.

Query for table column names returns no results to the calling code

I have a stored procedure query that I want to return the details of columns within a specific table. When I run the sp in Sql server managements studio I get results returned. The problem is when I try to execute the query from C# code. There are no exceptions thrown and the relevant persmissions are granted to execute the procedure in the database but no results are returned to the code. I'm using the enterprise application block version 3.1.
This is my query
SELECT SysObjects.[Name] as TableName,
SysColumns.[Name] as ColumnName,
SysTypes.[Name] As DataType,
SysColumns.[Length] As Length
FROM SysObjects INNER JOIN SysColumns ON SysObjects.[Id] = SysColumns.[Id]
INNER JOIN SysTypes ON SysTypes.[xtype] = SysColumns.[xtype]
WHERE SysObjects.[type] = 'U'
AND SysObjects.[Name] = 'MyTableName'
ORDER BY SysObjects.[Name]
C# Calling code
using (DbCommand dbCommand = db.GetStoredProcCommand("StoredProcedureName"))
{
DataSet data = new DataSet();
db.LoadDataSet(dbCommand, data, "MyTableName");
if (data.Tables.Count > 0 && data.Tables[0].Rows.Count > 0)
{
// Do stuff with the returned data
}
}
I'm not sure about the C# issue, but you should consider changing your query to use the data-abstraction layer provided by Microsoft. The use of the SYSOBJECTS references is not guaranteed to be the same between SQL Versions.
Instead I'd use this:
--
-- for a specific tables columns
--
select *
from INFORMATION_SCHEMA.COLUMNS
--
-- For all the user tables in the current database..
--
select *
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME='MyTableName'

Categories

Resources