How to populate datatable with all possible instances of certain data? - c#

I am having some trouble writing a SQL Server stored procedure. I have three tables, Products,CustomerInfo and CustomerOrders.
Products has columns ProductID,Product, Price, Description
CustomerInfo has columns CostumerID, Name, Address, Zipcode
CustomerOrders has columns like CustomerID or TransactionID, ProductID, Quantity.
Now I am trying to write a stored procedure which will import into a datatable all the products the customer has ever bought. I have the customers name that I can use as an parameter.
Couple of things to note: every time a customer purchases something, a new CustomerID and TransactionID are generated and they are both the same. The CustomerName is the only constant across multiple orders.
DECLARE #TransactionID int;
SET #TransactionID = #Id;
SELECT
P.Product, P.Price,
CP.TotalProducts as ProductQuantity
FROM
Products P
INNER JOIN
CustomerProducts CP ON CP.ProductID = P.ProductID
WHERE
CP.CustomerID = #TransactionID
At the moment, I get the products that the customer bought the last time he shopped. However, I want to get all products he has ever bought into one table. If anyone can help me out, I would really appreciate it!

If I understood you correctly you need joins on 3 tables in stored procedure to extract all details of customer purchased products.
so a stored procedure in this purpose could look like this-
CREATE PROC [dbo].[GetCustomerProductsById]
(
#CustId int=0
AS
BEGIN
SELECT P.ProductId ,P.Product,P.Price,P.Description,C.CustomerID,C.Name,C.Address FROM Products P
Inner Join CustomerOrders CO ON P.ProductId= CO.ProductID
Inner Join CustomerInfo C ON C.CustomerID = CO.CustomerID
WHERE C.CustomerID = #CustId
ORDER BY C.Name
END
Now once this is giving us the expected results then in c# code you can call this stored procedure like below and extract a result datatable.
SqlDataAdapter SqlAda;
DataSet ds;
using (SqlConnection Sqlcon = new SqlConnection(strCon))
{
using (SqlCommand cmd = new SqlCommand())
{
Sqlcon.Open();
cmd.Connection = Sqlcon;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "GetCustomerProductsById";
cmd.Parameters.Add(new SqlParameter("#CustId", SqlDbType.Int, 50));
cmd.Parameters["#CustId"].Value = <Your Input Source>;
SqlAda = new SqlDataAdapter(cmd);
ds = new DataSet();
SqlAda.Fill(ds);
Datatable dt = new DataTable();
dt = ds.Tables[0];
}
}

Related

Return multiple datasets from sql server stored procedure

I need to return through Web Api a Base64 XML output based upon calling a stored procedures which runs 5 different queries.
Stored procedure is not written ( I need to write it ) but there are 5 queries in which the data is completely different tables and columns etc... so I am wondering if this is even possible?
I know in Oracle you can return multiple cursors, but with SQL Server , can I return into asp.net 4.5 ( mvc c# / Ado.net) multiple datasets or collections? Any examples of this?
Example of just ONE of the queries
-- Content Tab
SELECT -- vTC.[TemplateId]
t.Name as "Client Name and Document" ,vTC.[SectionName] ,vTC.[ContentId] ,vTC.[ContentName]
,vTC.[ContentDescription],vTC.[ContentValue] ,CAL.ContentValue as "Spanish Content" , iif(S.IsClientSection = 1, 'Global Section','Template Section') as "Global or Template Section"
,DT.Title as DataType ,iif(vTC.IsRequired = 1, 'Yes', 'No') as "Required" ,vTC.[DisplayType]
FROM [dbo].[vwTemplateContent] vTC
left join dbo.Template t on vTC.TemplateId = t.TemplateId
left join dbo.DataType DT on vTC.DataTypeId = dt.datatypeid
left join dbo.Section S on S.SectionID = vTC.SectionID
left join [dbo].[ContentAlternateLanguage] CAL on vTC.ContentId = CAL.ContentID
where vTC.templateid in (1)
order by DisplayOrder
If you are going to get multiple tables then you have to write multiple select statements into your stored procedure like below:
CREATE PROCEDURE SPName
(
/*Declare your parameters*/
#parm1 dataType
)
AS
BEGIN
/*Write your select statements below*/
-- SELECT * FROM tblName
-- SELECT * FROM tblName2
END
You have to fill these records into your DataSet, DataSet supports multiple table into ADO.net.
Please refer below code to fill your DataSet:
SqlConnection con=new SqlConnection("YourConnection String");
SqlCommand cmd=new SqlCommand();
SqlDataAdapter da=new SqlDataAdapter();
DataSet ds = new DataSet();
cmd = new SqlCommand("SPName", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#parm1", id);//if you have parameters.
da = new SqlDataAdapter(cmd);
da.Fill(ds);
con.Close();
After this you can take advantage of different multiple recordsets using
ds.Tables[0]
ds.Tables[1]
..
Hope it will helps you
Thanks
Here's a basic example:
SQL Proc:
CREATE PROCEDURE usp_getStudentsAndClasses
#ClassName varchar(50)
, #IsActive bit
AS
BEGIN
--First select is first table
SELECT *
FROM Students
--Second select is second table, etc.
SELECT *
FROM Classes
--Third table...
--Can be more complex, as long as there is a result set
SELECT s.FirstName
, s.LastName
FROM Students s
JOIN StudentSeating ss
ON s.StudentID = ss.StudentID
JOIN Classes c
ON c.ClassID = ss.ClassID
WHERE s.IsActive = #IsActive
AND c.Name = #ClassName
END
C# function:
public DataSet GetDataSet(SqlConnection connection, string storedProcName, params SqlParameter[] parameters)
{
var command = new SqlCommand(storedProcName, connection) { CommandType = CommandType.StoredProcedure };
command.Parameters.AddRange(parameters);
var result = new DataSet();
var dataAdapter = new SqlDataAdapter(command);
dataAdapter.Fill(result);
return result;
}
C# usage:
var connection = new SqlConnection("Your_connection_string");
var parameters = new SqlParameter[]
{
new SqlParameter("ClassName", "Robotics"), //example of string value
new SqlParameter("IsActive", true) //example of numeric value
};
var dataSet = GetDataSet(connection, "usp_getStudentsAndClasses", parameters);
var firstTable = dataSet?.Tables?[0]; //use as any other data table...
Notice, it is almost the same code as you would use for a single-table stored procedure, except the data type returned is a DataSet, not a DataTable. A DataSet contains a DataTableCollection More info on MSDN
Yes, It is possible. You just need to write your select queries and you will get the data in a DataSet. If you have a single select query, you will get DataTable and if you have number of select queries (Say 5), then you will get a DataSet that has 5 DataTables. It is so simple. Just write your procedure and have fun.
Edit:
Example of Stored Procedure (pseudo code) is given below:
create Proc Name_Of_Proc
(
#FirstParam DataType,
#SecondParam DataType
)
AS
Begin
Select statement 1
Select statement 2
Select statement 3 --and so on upto n.
end
You need to do this in your database. After doing this, you need to execute this procedure from c# by using ADO.NET. You need to use SqlConnection SqlCommand and SqlDataReader object to do this. You can search on google or SO itself for more examples. One such link on SO is How to execute Stored procedure in c#

Populating Datagrid with Data from Multiple Tables

I need to populate a datagrid with the following columns.
invnumber,itemname,rate,quantity..
itemname,rate,quantity comes from 1 table while invnumber comes from another table
I used to do like this
string commandText = "SELECT invnumber,cname,date FROM inv_table WHERE invnumber LIKE #id";
SqlCommand command = new SqlCommand(commandText, conn);
string searchParam = String.Format("%{0}%", text_inv.Text);
command.Parameters.AddWithValue("#id", searchParam);
using (SqlDataAdapter sda = new SqlDataAdapter(command))
{
using (DataTable dt = new DataTable())
{
sda.Fill(dt);
dataGridView2.DataSource = dt;
}
}
Now i cannot directly assign the data source as 2 different tables are involved
dataGridView2.DataSource = dt;
How can i get around this.
To emit combined result from 2 or more different tables in a table, use either INNER JOIN, LEFT JOIN, RIGHT JOIN or UNION statement depending on your need.
In this case, you need to join first table and other table to get desired results, assume invnumber is unique or primary key. Here is an example:
string commandText = "SELECT other.invnumber, inv.cname, inv.date FROM inv_table AS inv
INNER JOIN other_table AS other
ON inv.invnumber = other.invnumber
WHERE other.invnumber LIKE #id";
Or if you have already defined classes for each table, use LINQ to SQL with lambda expression:
DataContext dc = new DataContext();
var results = dc.InvTable.Join(OtherTable, inv => inv.invnumber, other => other.invnumber, (inv, other) => new { invnumber = other.invnumber, cname = inv.cname, date = inv.date });
Any improvements and suggestions welcome.
Create a new class for the data structure of the 2 different table, populate the new one and use. (easier and the most clear solution)

Search data from two different tables that two tables in different databases

I have two tables in different SQL Server databases.
Database1 : table1 (custid, productid, customername )
Database2 : table2 (productname, productid, pice, mfg)
I want to display all the products purchased by particular custid.
My code:
using System.Data.SqlClient;
string queryString = "Select custID from Table1 where custId ="+ textbox1.text;
string TempCustID;
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(queryString, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
if (!reader.IsDBNull(0))
{
TempCustID = reader[0].ToString();
String stringprovider = "#database connection string ";
Sqlconnection con2 = new sqlconnection(stringprovider);
Con2.open();
Cmd2.connection=con2;
Cmd2.commandType = new commandType.text;
Cmd2.commandText = "select * from Table2 where Productid = #productid";
Cmd2.parameters.addwithvalue("#productid",TempCustID);
}
}
reader.Close();
Dataset Ds = new dataset();
Oledbdataadaptaer da1 = new oledbdataadapter(cmd2);
Datatable Table2 = new Data table();
Da1.fill(table2);
Datagridview2.source = table2;
}
In this I am getting only the first product details of that customer it's not displaying all the products at a time.
Separate this into two methods. First will fetch the customer IDs from database one based on the condition. Then pass those customer IDs to second method and fetch the product details. You may create list of customer IDs from first method and build SQL IN clause in second method. Refer
Building SQL “where in” statement from list of strings in one line?
Change your select statement. join the two tables using INNER JOIN with their productid
SELECT *
FROM Table2
INNER JOIN Table1 ON TABLE2.productid = Table1.productid
WHERE Table2.productid = #productid
That will display all records in two tables, if you want to select specific tables, just remove (*) and replace with the column names you want.
SELECT
Table1.customername, Table2.productname, Table2.productid,
Table2.pice, Table2.mfg
FROM
Table2
INNER JOIN
Table1 ON TABLE2.productid = Table1.productid
WHERE
Table2.productid = #productid
Hope my sample code above helps you. :)
You are selecting custID from Table1... Instead of that select productid from Table 1 depending upon customerID
Modify your first query as :
string queryString = "Select productid from Table1 where custId ="+ textbox1.text;
also command is executing outside the loop...

Loading DataTable with multiple tables select query

I never used select queries with multiple tables involved before and now when I do, I'm having troubles with getting the information from the DataTable.
I have this query:
SELECT *
FROM [Usergroups], [Groups]
WHERE [Usergroups.UserID] = #name
AND [Groups.GroupID] = [Usergroups.GroupID]
And this is how I get the returned values into a DataTable:
DataTable groupsTable = new DataTable();
groupsTable.Load(sqlCmd.ExecuteReader());
Now, how can I specify my DataTable from which table I want to take rows from? For example, this is what I did before multiple tables where involved:
string groupName = groupsTable.Rows[0]["Name"];
I could not find any resource with such information, but I know it's a basic question. Thanks in advance.
The query in your question doesn't produce, as a result, multiple tables.
It produces a JOIN between two tables.
As a consequence, on the C# side, you don't have two tables but just one as before, with the all fields from both tables.
As a side note, a better way to JOIN tables together is through the use of the JOIN statement like this
SELECT * -- a field list is better here ---
FROM Usergroups ug INNER JOIN Groups g ON g.GroupID=ug.GroupID
WHERE ug.UserID=#name
and you should add, to the SELECT clause, a list of the fields that you are really interested in.
SEE a simple JOIN reference
If you want to retrieve the values of the two tables in separate DataTable objects, then you need to use a DataSet in this way
DataSet ds = new DataSet();
DataTable dtUserGroups = new DataTable("UserGroups");
DataTable dtGroups = new DataTable("Groups");
ds.Tables.Add(dtUserGroups );
ds.Tables.Add(dtGroups);
using(SqlCommand cmd = new SqlCommand("SELECT * FROM UserGroups;SELECT * from Groups", con))
{
using(SqlDataReader dr = cmd.ExecuteReader())
{
ds.Load(dr, LoadOption.OverwriteChanges, dtUserGroups, dtGroups);
// Now you have the two tables filled and
// you can read from them in the usual way
}
}
This last example could further enhanced adding a DataRelation object to the DataSet to represent the relationship between the two tables. This could allow your code to navigate the parent/child recordset.
You may try in this way :
string query = "SELECT U.ID,U.NAME, C.NAME AS CUSTOMERNAME, C.DOB FROM USER U INNER JOIN CUSTOMER C ON U.ID = C.USERID"
SqlConnection conn = new SqlConnection(_connectionString);
SqlCommand cmd = new SqlCommand(query, conn);
SqlDataAdapter adp = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
adp.Fill(dt);
Above code will return you one DataTable with data from two different tables say "User" and "Customer".
I hope now you know how to access data from a DataTable.
It is better to use JOIN for combining multiple tables such as INNER JOIN, LEFT OUTER JOIN, RIGHT OUTER JOIN, FULL JOIN as per your requirements. So, when you use INNER JOIN, it will have the columns of two joined tables, i.e., if
tblA has a, b,c as columns and
tblB has a, e,f as columns
then the inner joined table will have a, b, c, e, f as its columns.
Then, you can use like this:
public DataTable LoadData()
{
DataTable dataTable;
string connString = #"your connection string here";
string query = "SELECT * FROM Usergroups t1 INNER JOIN Groups t2 ON t2.GroupID=t1.GroupID WHERE t1.UserID=#name";
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(query, conn);
conn.Open();
// create data adapter
SqlDataAdapter da = new SqlDataAdapter(cmd);
// this will query your database and return the result to your datatable
da.Fill(dataTable);
conn.Close();
return dataTable;
}
After Getting the DataTable, then you can use this table like:
DataTable dt = LoadDataClass.LoadData();
string groupName = dt.Rows[0]["Name"]; //For first row
I hope you get it.
in wpf c#, this method can also be used to retrieve data from multiple tables
try
{
using (SqlConnection conn = new SqlConnection(_pageDataBase.connectionString()))
{
conn.Open();
DataTable dt = new DataTable();
SqlDataAdapter Usergroups= new SqlDataAdapter("select *from Usergroups", conn);
Usergroups.Fill(dt);
SqlDataAdapter Groups= new SqlDataAdapter("select *from Groups", conn);
Groups.Fill(dt);
datagridName.ItemsSource = dt.DefaultView;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

merging two datasets and display in one gridview

I have two seperate databases from which I want to retrieve data and display in one grid view. The difficult I have is that I have a product key only in the table from the one database and the same set of product keys agains the actual products products in the other database and now I want to display the product data in one grid view....if this makes sense.
How can I do this, merge the data and display the product data agains the keys in the one grid.
string connString = "Data Source=.\\SQLEXPRESS;Initial Catalog=LRVWebsite;user ID=sa;password=lrmg;";
SqlConnection sqlCon;
OleDbConnection conn;
DataSet setOleDb;
DataSet dsSql;
private void bindData()
{
try
{
conn = new OleDbConnection(#"Provider=Microsoft.Jet.OleDb.4.0;
Data Source =" + Server.MapPath("App_Data\\LR Product Database 2000.mdb"));
conn.Open();
setOleDb = new DataSet();
OleDbDataAdapter dbaOle = new OleDbDataAdapter("SELECT * FROM tblProducts", conn);
dbaOle.Fill(setOleDb);
sqlCon = new SqlConnection(ConfigurationManager.ConnectionStrings["LRVWebsite"].ToString());
sqlCon.Open();
dsSql = new DataSet();
SqlDataAdapter dba = new SqlDataAdapter(#"SELECT C.CustomerFirstName,C.CustomerLastName, C.CustomerCompany,C.CustomerPosition,C.CustomerCountry,C.CustomerProvince,C.CustomerContact,CP.ActionDate,CP.ProductCode,CP.CustomerEmail FROM tblCustomers C INNER JOIN tblCustomerProducts CP ON C.CustomerEmail = CP.CustomerEmail ORDER BY ActionDate DESC", connString);
//#"SELECT C.CustomerFirstName,C.CustomerLastName,C.CustomerCompany,C.CustomerPosition,C.CustomerCountry,C.CustomerProvince,C.CustomerContact,CP.ActionDate,CP.ProductCode,CP.CustomerEmail FROM tblCustomers C INNER JOIN tblCustomerProducts CP ON C.CustomerEmail = CP.CustomerEmail ORDER BY ActionDate DESC", connString);
dba.Fill(dsSql);
dsSql.Merge(setOleDb);
GridView1.DataSource = dsSql;
GridView1.DataBind();
sqlCon.Close();
This is what I have tried.Now, how can I get the product key to correlate with the actual product in the other table which contains the same product key?
I think this is a commonly faced scenario. Here is a detailed link from msdn.
Merge Data Set Contents
As much as I understand, you have 2 tables in one database and one table in the other database and you are wanting to combine all of these data set and display it as one.
If I am correct then you can do joins across the databases;
select * from dbo.firstdatabasetable db1
inner join apple.primarykeys db2
on db2.primary = db1.primary
inner join orange.seconddatabase db3
on db2.productname = db3.productname
If databases are hosted on different Machines across the network then you can find the DB servers with select sys.servers
Lets say the the first server is x and the second one is y
then;
select * from x.dbo.firstdatabasetable db1
inner join x.dbo.primarykeys db2
on db2.primary = db1.primary
inner join y.dbo.seconddatabase db3
on db2.productname = db3.productname
inner join x.dbo.primarykeys

Categories