I have two tables (1-N relationship).
(ID,name,surname),
(ID,Job(s),role,society).
In my app I want to merge table1 and table2 (based on the id that binds the two tables) BUT i want to hide the columns that COULD be empty.
Example: (in this case, i don't want to show 'ruolo/grado')
How I wrote the code for this:
CREATE PROCEDURE spEstraiPbyId
#Id int
as
begin
SELECT * from Persone
join Lavori on Persone.Id = #Id and Lavori.IdPersona=#Id
end
PS: I have already seen several similar questions on the internet but no answer was able to satisfy my request or I did not understand correctly. I hope you can help me willingly.
If I understand it correctly, you want to do something like this:
http://sqlfiddle.com/#!18/04141/3
SELECT * from Persone
join Lavori on Persone.Id = Lavori.IdPersona where Lavori.Job is not null
First, use the on joining the keys, and then filter with a where those that are not null :)
Thank you all. Best tip was written by #Serg because to do this i worked on client side, with DataReader and Datatable objs:
DataTable tbl = new DataTable()
SqlCommand cmd = new SqlCommand("spEstraiPById", cnn); //See at the end for spEstraiPById
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("Id",txtNickname.Text);
using (SqlDataReader rdr = cmd.ExecuteReader())
{ //Add columns to the table
tbl.Columns.Add("ID");
tbl.Columns.Add("Nome");
tbl.Columns.Add("Cognome");
tbl.Columns.Add("Residenza");
tbl.Columns.Add("Professione");
tbl.Columns.Add("Ruolo");
tbl.Columns.Add("Società");
while (rdr.Read())
{ //from DB to Table
DataRow drw = tbl.NewRow();
drw["ID"] = rdr["Id"];
drw["Nome"] = rdr["Nome"];
drw["Cognome"] = rdr["Cognome"];
drw["Residenza"] = rdr["Residenza"];
drw["Professione"] = rdr["Professione"];
drw["Ruolo"] = rdr["Ruolo/Grado"];
drw["Società"] = rdr["Società"];
tbl.Rows.Add(drw);
}
foreach (DataRow row in tbl.Rows) //Deleting empty records
{
for (int col = tbl.Columns.Count - 1; col >= 0; col--)
{
if (row.IsNull(col))
{
tbl.Columns.RemoveAt(col);
}
}
// No need to continue if we removed all the columns
if (tbl.Columns.Count == 0)
break;
}
}
gw1.DataSource = tbl;
gw1.DataBind();
cnn.Close();
//=Stored Procedure
CREATE PROCEDURE spEstraiPbyId
#Id int
as
begin
SELECT * from Persone
join Lavori on Persone.Id = #Id and Lavori.IdPersona=#Id
end
I am trying to populate a combo box based off of the value member that has been selected from a data grid view.
Here is my code to initialise it
DataSet dsCIF2 = new DataSet();
DataRow drPitch;
String sqlPitch = #" Select * from Pitch";
String connStr5 = Properties.Resources.cString;
SqlDataAdapter daPitch = new SqlDataAdapter(sqlPitch, connStr5);
DataTable dtPitch = new DataTable();
daPitch.Fill(dtPitch);
daPitch.Fill(dsCIF2, "Pitch");
comboBox2.DisplayMember = "PitchDesc";
comboBox2.ValueMember = "PitchID";
comboBox2.DataSource = dtPitch;
With the following code I use this to find the ID of the pitch from the selected row on the data grid view and it returns the correct pitch ID, as seen through debugging.
int matchBookingID = 0;
matchBookingID = Convert.ToInt32(DGV.SelectedRows[0].Cells[0].Value);
drMatchData = dsCIF.Tables["MatchStats"].Rows.Find(matchBookingID);
Pitch = Convert.ToInt32(drMatchData["PitchID"].ToString());
Now when I try to use that ID to find the datarow within the pitch table I get an error saying
Table doesn't have a primary key
on this line of code
drPitch = dsCIF2.Tables["Pitch"].Rows.Find(Pitch);
I don't know why I am getting this error, thanks in advance!
Update: The table does have a primary key
SQL CODE
create TABLE PITCH
(
PitchID int NOT NULL,
PitchDesc varchar(30) NOT NULL,
CONSTRAINT pkPitchID PRIMARY KEY(PitchID),
)
Turns out I forgot to fill the schema of the table. It works now that I have added the following line of code to the initialisation code
daPitch.FillSchema(dsCIF2, SchemaType.Source, "Pitch");
It now looks like this
DataSet dsCIF2 = new DataSet();
String sqlPitch = #" Select * from Pitch";
String connStr5 = Properties.Resources.cString;
SqlDataAdapter daPitch = new SqlDataAdapter(sqlPitch, connStr5);
SqlCommandBuilder cmdBPitch = new SqlCommandBuilder(daPitch);
daPitch.FillSchema(dsCIF2, SchemaType.Source, "Pitch");
DataTable dtPitch = new DataTable();
daPitch.Fill(dtPitch);
daPitch.Fill(dsCIF2, "Pitch");
I need write simple class in C#. I have 2 tables. But for understanding I use just 1 table.
public string[] GetCustOrders(int CustomerCODE)
{
SqlConnection myConn = new SqlConnection("server=(local);Initial Catalog=dbName;Integrated Security=True");
SqlDataAdapter myData = new SqlDataAdapter("CustOrdersOrdersDetails", myConn);
myData.SelectCommand.CommandType = CommandType.StoredProcedure;
myData.SelectCommand.Parameters.Add(new SqlParameter("#CustomerCODE", SqlDbType.Int, 0));
myData.SelectCommand.Parameters["#CustomerCODE"].Value = CustomerCODE;
// string[] as = string[6];
string[] as1 = string[3];
// string[] as2 = string[3];
DataSet ds = new DataSet();
myData.Fill(ds);
return as;
}
And my stored procedure code:
CREATE PROCEDURE CustOrdersOrdersDetails
#CustomerCODE int
AS
SELECT
Name,
Action,
Comments
FROM
System2
WHERE
Code = #CustomerCODE
The stored procedure will select just 1 row from the table. But I dont know how fromSqlDataAdapter` get each value of cell of this one row and give this value for my array as1.
Ex., "as[1]=" and after = I need give value of Action from selected row.
I know this simple, but I think... and think, that I can do this just give all values of my row to the DataSet and after that give each value of each cell to each string from my array. But I tray and cant finish this class...
Can anyone help?
int i = 0;
// For each table in the DataSet, print the row values.
foreach(DataTable table in ds.Tables)
{
foreach(DataRow row in table.Rows)
{
foreach (DataColumn column in table.Columns)
{
as[i]=row[column]);
i++;
}
}
}
I am trying to insert categories and subcategories from Excel into a database table.
I have 1 Excel file which contains some data and from this Excel file I am creating dataset which contains lots of datatables.
In this dataset I have 2 datatables in the form of this:
Datatable 0 with records:Category
ParentCategory Description
Electronics jhdkhsd
Sports kjshfhs
Datatable 1 with records:SubCategory
Subcategory ParentCategory Description
Mobile Electronics weprwp
Tv Electronics sdflskd
Balls Sports kjshdfkjh
Shoes Sports uytuyt
Now my database tables are like this:
Category:Id,Name,Description,parentid
So far I am successful inserting parent category but now trying to insert child categories but that is where currently i am struggling.
This my code so far:
var dsFinal = new DataSet();
//Some code to read excel sheets and data from excel and create datatables and records with it.
dsControlSheet.Tables[0].Columns.Add("Id");
DataColumn parentId = new DataColumn("ParentId", typeof(int));
parentId.DefaultValue = 0;
dsFinal.Tables[0].Columns.Add(parentId);
dsFinal.Relations.Add("Abc",dsFinal.Tables[0].Columns["ParentCategory"],
dsFinal.Tables[1].Columns["ParentCategory"],false); //creating relation ship between Category datatable
// and SubCategory datatable on field ParentCategory
using (SqlConnection connection = new SqlConnection(""))
{
SqlDataAdapter adapter = new SqlDataAdapter();
var insertCommand = new SqlCommand("insert into Category (Name,Description) values (#ParentCategory,#Description) SET #Id = SCOPE_IDENTITY()", connection);
var parameter = insertCommand.Parameters.Add("#Id", SqlDbType.Int, 0, "Id");
insertCommand.Parameters.Add("#ParentCategory", SqlDbType.NVarChar, 50, "ParentCategory");
insertCommand.Parameters.Add("#Description", SqlDbType.NVarChar, 50, "Description");
parameter.Direction = ParameterDirection.Output;
insertCommand.UpdatedRowSource = UpdateRowSource.OutputParameters;
adapter.InsertCommand = insertCommand;
adapter.Update(dsFinal.Tables[0]); //successfully inserted parent category and got autoincremented value in Id column of my 0th datatable
//trying to insert child category using above insert command
foreach (DataRow parentCategory in dsFinal.Tables[0].Rows)
{
var child = parentCategory.GetChildRows("Abc").CopyToDataTable();//get child category of particular parent
adapter.Update(child);
}
}
Here in the last loop to insert child category; I am confused about how to use
same insertCommand variable to insert child category?
Update:I have used datatable Expression to calculate parentid like this:
using (SqlConnection connection = new SqlConnection(""))
{
SqlDataAdapter adapter = new SqlDataAdapter();
var insertCommand = new SqlCommand("insert into Category (Name,Description) values (#ParentCategory,#Description) SET #Id = SCOPE_IDENTITY()", connection);
var parameter = insertCommand.Parameters.Add("#Id", SqlDbType.Int, 0, "Id");
insertCommand.Parameters.Add("#ParentCategory", SqlDbType.NVarChar, 50, "ParentCategory");
insertCommand.Parameters.Add("#Description", SqlDbType.NVarChar, 50, "Description");
parameter.Direction = ParameterDirection.Output;
insertCommand.UpdatedRowSource = UpdateRowSource.OutputParameters;
adapter.InsertCommand = insertCommand;
adapter.Update(dsFinal.Tables[0]); //successfully inserted parent category and got autoincremented value in Id column of my 0th datatable
//For inserting child category..
//added column parentid to store child category
SqlDataAdapter da = new SqlDataAdapter();
dsFinal.Tables[1].Columns.Add("ParentId", typeof(int), "IIF(Parent.ParentCategory=ParentCategory,parent.Id,0)");
var insertChildCategoryCommand = new SqlCommand("insert into Category (Name,Description,ParentId) values (#Subcategory,#Description,#ParentId) SET #Id = SCOPE_IDENTITY()", connection);
var parameter1 = insertChildCategoryCommand.Parameters.Add("#Id", SqlDbType.Int, 0, "Id");
insertChildCategoryCommand.Parameters.Add("#Subcategory", SqlDbType.NVarChar, 50, "Subcategory");
insertChildCategoryCommand.Parameters.Add("#Description", SqlDbType.NVarChar, 50, "Description");
insertChildCategoryCommand.Parameters.Add("#ParentId", SqlDbType.int, 0, "ParentId");
parameter1.Direction = ParameterDirection.Output;
insertChildCategoryCommand.UpdatedRowSource = UpdateRowSource.OutputParameters;
da.InsertCommand = insertChildCategoryCommand;
//Error here that computed column cannot be inserted.Here computed column is parentid
da.Update(dsFinal.Tables[1]);
}
Error:Computed column(parentid) cannot be inserted.
You are almost there with latest code.
The only problem is that the calculated columns are not allowed to be used for inserting/updating the database table. Btw, the error message is not "Computed column(parentid) cannot be inserted.", but:
The column mapping from SourceColumn 'ParentId' failed because the DataColumn 'ParentId' is a computed column.
I could agree that the message could have been better, and also I didn't find any documentation describing that. Most probably the rationale is that the computed columns are not normally stored.
Whatever the reason is, that's the reality. You have no other choice than creating a regular column and populating it with data manually.
There are many ways to do that (both efficient and ineffient), but once you already created a relation, you can use the DataRow.GetParentRow method to locate the related category record.
With all that being said, replace the line
dsFinal.Tables[1].Columns.Add("ParentId", typeof(int),
"IIF(Parent.ParentCategory=ParentCategory,parent.Id,0)");
with the following snippet:
var dtSubCategory = dsFinal.Tables[1];
dtSubCategory.Columns.Add("ParentId", typeof(int));
foreach (var drSubCategory in dtSubCategory.AsEnumerable())
{
var drCategory = drSubCategory.GetParentRow("Abc");
drSubCategory["ParentId"] = drCategory != null ? drCategory["Id"] : 0;
}
and you are done.
EDIT: Let me make it clear. The only time critical operation here is locating the category id by name. Using the relation and GetParentRow is equivalent of the evaluating the expression accessing parent as in your attempt. Data relation internally maintains a lookup structure for supporting such operations.
If you want to get the best possible performance, then don't create a relation, but a dictionary. What you need is given a name (string), find the corresponding id (int), so Dictionary<string, int> is a perfect candidate for that:
var categoryIds = dsFinal.Tables[0].AsEnumerable().ToDictionary(
dr => dr.Field<string>("ParentCategory"), // key
dr => dr.Field<int>("Id") // value
);
var dtSubCategory = dsFinal.Tables[1];
dtSubCategory.Columns.Add("ParentId", typeof(int));
foreach (var drSubCategory in dtSubCategory.AsEnumerable())
{
int categoryId;
categoryIds.TryGetValue(drSubCategory.Field<string>("ParentCategory"), out categoryId);
drSubCategory["ParentId"] = categoryId;
}
Change your relation so it's using Id and ParentId and your first solution will be working just right.
When you will update that first table and the get the autoincremented value, it will automatically update the second table via the relation. Here is an example.
DataSet ds = new DataSet();
DataTable dt = new DataTable();
var colParent = dt.Columns.Add("id", typeof(int));
DataTable dtChild = new DataTable();
var colChild = dtChild.Columns.Add("parentid", typeof(int));
ds.Tables.Add(dt);
ds.Tables.Add(dtChild);
ds.Relations.Add("relation1", colParent, colChild);
DataRow rowParent = dt.NewRow();
rowParent["id"] = 1;
dt.Rows.Add(rowParent);
DataRow rowChild = dtChild.NewRow();
rowChild["parentid"] = rowParent["id"];
dtChild.Rows.Add(rowChild);
// at this point, parentid from rowChild is "1".
rowParent["id"] = 10; // DataAdapter.Update simulation.
// and now parentid from rowChild has been update via the relation to "10".
When using this method, i'll usually set my column to get a temporary "id" value by setting the column as an identity column with a seed and step set to -1. This would go after the third line.
colParent.AutoIncrement = true;
colParent.AutoIncrementSeed = -1;
colParent.AutoIncrementStep = -1;
Unless you really need to have your relation on those string fields, there's no need to do any loop, computed column or anything overly complicated.
Hi I have a dropdown list and I want to update one item when I selecting it in dropdown list,I wrote this code but it only update the first item:
DBMethod db = new DBMethod();
DataTable dt = new DataTable();
string sqlcmd = "select * from dbo.Web_Personnel ";
dt = db.ReturnTableWithData(sqlcmd);
dt.Rows[0]["Job"] = txtjobE.Text;
dt.Rows[0]["ChildNo"] = txtchildnoe.Text;
dt.Rows[0]["Salary"] = txtsalary.Text;
db.UpdateDatatable(dt, "dbo.Web_Personnel");
yes this code by default will only update the first item because you are hard coding value 0 in it
dt.Rows[0]["Job"] = txtjobE.Text;
dt.Rows[0]["ChildNo"] = txtchildnoe.Text;
dt.Rows[0]["Salary"] = txtsalary.Text;
just declare a variable
int i = 0;
//change the value of I to desired value and less than dt.Rows.Count()
dt.Rows[i]["Job"] = txtjobE.Text;
dt.Rows[i]["ChildNo"] = txtchildnoe.Text;
dt.Rows[i]["Salary"] = txtsalary.Text;
Target a particular row using a variable i:
Identify the DB row to edit, eg:
int i = idOfUser // e.g. id = 3
dt.Rows[i]["Job"] = txtjobE.Text;
dt.Rows[i]["ChildNo"] = txtchildnoe.Text;
dt.Rows[i]["Salary"] = txtsalary.Text;