Problem while nesting DataTable - asp.net

I am trying to achieve nesting in DataTable, i.e. a column of DataTable is a DataTable. My code is something like this:
DataTable table = new DataTable();
DataColumn column = new DataColumn("Qualifications", System.Type.GetType("System.Data.DataTable"));
table.Columns.Add(column);
I am getting a runtime error message at line # 2, that says "Column requires a valid DataType". What could be the reason?

I would say that what you are attempting to achieve is not possible using the way you specified. To achieve a relationship between an entity and several sub-entities use a one-to-many relationship between one table and another table.
This means you have two separate tables, call them for instance TableOne and TableMany. In TableOne put all the fields that describe your entity, and make sure to have a primary key. In TableMany put all the fields that describe your sub-entities, and include a field which is of the type of the TableOne primary key field, which relates each sub-entity to its owning entity.
For examle:
TableOne:
int PrimaryKey
nvarchar(50) Name
TableMany:
int ForeignKey
nvarchar(50) Qualification
int Grade
TableOne sample content:
PrimaryKey Name
1 Alice
2 Bob
3 Charlie
TableMany sample content:
ForeignKey Qualification Grade
1 Driving 100
1 Acting 60
1 Singing 30
2 Driving 40
2 Piloting 90
2 Snowboarding 80
3 Dancing 70
3 Tennis 30
Example Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace datatests
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
p.Main();
}
DataSet dataSet;
DataTable TableOne, TableMany;
DataRelation OneToManyRelation;
void Main()
{
dataSet = new DataSet();
TableOne = new DataTable();
var TableOnePK = TableOne.Columns.Add("PrimaryKey", typeof(int));
TableOne.Columns.Add("Name", typeof(string));
TableMany = new DataTable();
var TableManyFK = TableMany.Columns.Add("ForeignKey", typeof(int));
TableMany.Columns.Add("Qualification", typeof(string));
TableMany.Columns.Add("Grade", typeof(int));
dataSet.Tables.Add(TableOne);
dataSet.Tables.Add(TableMany);
TableOne.Constraints.Add("PK", TableOnePK, true);
OneToManyRelation = new DataRelation("OneToMany", TableOnePK, TableManyFK);
TableOne.ChildRelations.Add(OneToManyRelation);
// Populate TableOne with sample data.
AddTableOneRow(1, "Alice");
AddTableOneRow(2, "Bob");
AddTableOneRow(3, "Charlie");
// Populate TableMany with sample data.
AddTableManyRow(1, "Driving", 100);
AddTableManyRow(1, "Acting", 60);
AddTableManyRow(1, "Singing", 30);
AddTableManyRow(2, "Driving", 40);
AddTableManyRow(2, "Piloting", 90);
AddTableManyRow(2, "Snowboarding", 80);
AddTableManyRow(3, "Dancing", 70);
AddTableManyRow(3, "Tennis", 30);
var parentRow=TableOne.Rows[0];
var childRows = parentRow.GetChildRows(OneToManyRelation);
Console.WriteLine("Data for record key #{0}, Name={1}",
parentRow["PrimaryKey"],
parentRow["Name"]);
Console.WriteLine("Qualifications:");
foreach (DataRow childRow in childRows)
{
Console.WriteLine(" {0}: {1}",
childRow["Qualification"],
childRow["Grade"]);
}
}
private void AddTableManyRow(int fk, string qual, int grade)
{
var newRow = TableMany.NewRow();
newRow["ForeignKey"] = fk;
newRow["Qualification"] = qual;
newRow["Grade"] = grade;
TableMany.Rows.Add(newRow);
}
private void AddTableOneRow(int key, string name)
{
var newRow = TableOne.NewRow();
newRow["PrimaryKey"] = key;
newRow["Name"] = name;
TableOne.Rows.Add(newRow);
}
}
}
Sample output:
Data for record key #1, Name=Alice
Qualifications:
Driving: 100
Acting: 60
Singing: 30

Related

Inserting elements of one List To Another

I am new to programming. I am retrieving a column Price from my database and saving it into a list. I want to perform some multiplication with that data and want to store the result after multiplication into another list. Here is the code i wrote to fetch data and store it into a list.
SqlDataAdapter da = new SqlDataAdapter("Select Price from FoodPackages",con);
DataSet dataset = new DataSet();
da.Fill(dataset, "FoodPackages");
List<int> package_price = new List<int>();
foreach(DataRow row in dataset.Tables["FoodPackages"].Rows)
{
package_price.Add(Convert.ToInt32(row["Price"]));
}
for( int i = 0; i<package_price.Count; i++)
{
int food = guest * package_price[i]; // Food = The total food cost
}
The line in which i am multiplying guest with each element of list. Here i have an integer variable but instead of this i want a list. Kindly help me do this.
Thanks in advance
If I understand you correctly like this:
SqlDataAdapter da = new SqlDataAdapter("Select Price from FoodPackages",con);
DataSet dataset = new DataSet();
da.Fill(dataset, "FoodPackages");
List<int> package_price = new List<int>();
foreach(DataRow row in dataset.Tables["FoodPackages"].Rows)
{
package_price.Add(Convert.ToInt32(row["Price"]));
}
// Initialize a new list
List<int> myList = new List<int>();
for( int i = 0; i<package_price.Count; i++)
{
int food = guest * package_price[i]; // Food = The total food cost
// Add element into the list
myList.Add(food);
}
ADD: If a "guest" variable is not type of int, then you have to create List of decimal:
List<decimal> myList = new List<decimal>();
for( int i = 0; i<package_price.Count; i++)
{
//int food = guest * 20; // this line is not necessary
// You can calculate and add element into the list at once
myList.Add(guest * 20);
}

Database value in label asp.net c#

I am trying to get value from database to be display in label. First i have to get the value of the dropdownlist and retrieved from database based on it. After that, I need to get the titlePromo column into my Label.
Currently i have the code out but i am not sure if it is the right one. There is no error but it displayed the membershipType column instead of the titlePromo.
ID titlePromo membershipType defaults
-- ---------- -------------- ------
1 Promo 1 Membership Promotion Y
2 Promo 2 Membership Renewal Y
3 Promo 3 Membership Grad Y
4 Promo 4 Membership Promotion N
5 Promo 5 Membership Promotion N
6 Promo 6 Membership Grad N
My codes that i have done so far:
string strConnectionString = ConfigurationManager.ConnectionStrings["FYPDB"].ConnectionString;
SqlConnection myConnect = new SqlConnection(strConnectionString);
string strCommandText2 = "select * FROM FYPDB.dbo.Promotions where membershipType = '%' + #membership + '%' AND defaults = 'Y'";
string ddlmembership = ((DropDownList)dvInsertPromotion.FindControl("ddlAddMembershiplist")).SelectedItem.ToString();
cmd.Parameters.Add("#membership", SqlDbType.NVarChar);
cmd.Parameters["#membership"].Value = ddlmembership;
DataSet da2 = dal.retrieveTitle(ddlmembership);
SqlCommand cmd2 = new SqlCommand(strCommandText2, myConnect);
((Label)pnlDefaultPopup.FindControl("Label13")).Visible = true;
((Label)pnlDefaultPopup.FindControl("Label13")).Text = da2.Tables[0].Rows[0]["titlePromo"].ToString();
html:
.cs
public DataSet retrieveTitle(String membership)
{
SqlParameter[] parameters = new SqlParameter[]{
new SqlParameter("#membership", SqlDbType.NVarChar),
};
parameters[0].Value = membership;
DataSet ds = new DataSet();
ds = commons.ExecuteDataSet("Select * FROM Promotions WHERE (membershipType = '" + membership + "') AND defaults = 'Y' ");
return ds;
}
Before giving you my suggestion I would like to make some remarks to your existing code:
you should select only the titlePromo in your query, as you only need one field, and not the entire row (therefore you wouldn't need a dataset in the first place)
the naming of your function is not according to its scope, at it does not retrieve the title, but an entire entry in the promotions table.
in this structure "membershipType = '%' + #membership + '%'" the syntax is not correct. The wildcards are used together with the "like" keyword
Bellow, you can find my code sample of how would I implement it if I were you:
static void Main(string[] args)
{
using (SqlConnection PubsConn = new SqlConnection(yourConnectionString))
{
//code to retrieve membership
var membership = "Membership Promotion";
var title = retrieveTitle(PubsConn, membership);
//code to set up label
}
}
public static string retrieveTitle(SqlConnection conn, String membership)
{
conn.Open();
var title = string.Empty;
string strCommandText = "select top 1 titlePromo FROM Promotions where membershipType = #membership AND defaults = 'Y'";
SqlCommand commmand = new SqlCommand(strCommandText, conn);
commmand.Parameters.AddWithValue("#membership", membership);
try
{
using (SqlDataReader reader = commmand.ExecuteReader())
{
if (reader != null && reader.Read())
{
title = Convert.ToString(reader["titlePromo"]);
}
}
}
catch (Exception ex)
{
Console.WriteLine("Error while retrieving table: " + ex.Message);
}
conn.Close();
return title;
}
If you want to use wildcards and 'like', you can do it like this:
string strCommandText = "select top 1 titlePromo FROM membershipTest where membershipType like #membership AND defaults = 'Y'";
SqlCommand commmand = new SqlCommand(strCommandText, conn);
commmand.Parameters.AddWithValue("#membership", "%" + membership + "%");

Need to insert a data row multiple times in the database

I have two data tables in sql. I need to insert data feom one table to another. My first data table Table1 contain data column Code,Model,Num,Qty and second table Table2 also contain the same. But I need to insert the data from table1 to table2 multiple times. If Qty in Table1 is 4 then, insert the data of
Table1 for 4 times according to the quantity.
protected void Button15_Click3(object sender, EventArgs e)
{
for (int i = 0; i < 4; i++)
{
String str1 = "insert into Table2(Code, Model, Num, Qty) select Code, Model, Num, Qty from Table1;";
SqlCommand xp1 = new SqlCommand(str1, con);
con.Open();
SqlDataAdapter da1 = new SqlDataAdapter();
da1.SelectCommand = xp1;
DataSet ds1 = new DataSet();
da1.Fill(ds1, "Code");
GridView1.DataSource = ds1;
con.Close();
}
}
}
In this program I give Number 4 manually, but I need to take it from my database qty. How can I put the SQL column name qty in the loop to insert the data at multiple time?
You can give a try like this:
private void button1_Click(object sender, EventArgs e)
{
string connetionString = null;
SqlConnection connection ;
SqlDataAdapter adapter = new SqlDataAdapter();
DataSet ds = new DataSet();
int i = 0;
int j = 0;
connetionString = "Data Source=ServerName;Initial Catalog=DatabaseName;User ID=UserName;Password=Password";
connection = new SqlConnection(connetionString);
try
{
connection.Open();
adapter.SelectCommand = new SqlCommand("Your SQL Statement Here", connection);
adapter.Fill(ds);
connection.Close();
for(j=0;j<=ds.Tables[0].Rows.Count;j++){
for (i = 0; i <= Convert.ToInt32(ds.Tables[0].Rows[j]["Qty"].ToString()); i++)
{
String str1 = "insert into Table2(Code, Model, Num, Qty)
select Code, Model, Num, Qty from Table1;";
SqlCommand xp1 = new SqlCommand(str1, con);
con.Open();
SqlDataAdapter da1 = new SqlDataAdapter();
da1.SelectCommand = xp1;
DataSet ds1 = new DataSet();
da1.Fill(ds1, "Code");
GridView1.DataSource = ds1;
con.Close();
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
I hope it is clear now. !
As pointed out in the comments, duplicating rows isn't a good idea without a primary key on both the source and destination tables, as otherwise identification of rows will become problematic.
You haven't mentioned whether you want to copy just one row, multiple rows, or the whole table N times over, but assuming the latter, bulk IO jobs like this is better suited to doing the whole operation within the database server, in order to reduce the IO transferring data back and forth between your app and the database.
Assuming both tables are in the same database, here's a way you can do this with a row-duplicating recursive CTE. If you need to control the #CopyCount from C#, just bind it as an integer and execute it with SqlCommand.ExecuteNonQuery:
DECLARE #CopyCount INT = 10;
with cteRowGen AS
(
SELECT 1 AS RowNum
UNION ALL
SELECT RowNum + 1
FROM cteRowGen
WHERE RowNum < #CopyCount
)
insert into Table2(Code,Model,Num,Qty)
select Code,Model,Num,Qty
from table1 CROSS JOIN cteRowGen;
Like StuartLC pointed out, CTE is the way to go.
Here's a version that will read the QTY from your table1
It will also insert 1 for the Qty in Table2, and not 4
DECLARE #Cnt INT = (SELECT Qty FROM Table1);
WITH data AS (
SELECT 1 AS RowCnt
UNION ALL
SELECT RowCnt + 1
FROM data
WHERE RowCnt < #Cnt
)
INSERT INTO Table2
SELECT Code, Model, Num, 1 as Qty
FROM Table1 a
CROSS JOIN data

Get Distinct data from datatable present in webservices using linq

I want to get only single row from multiple rows with same projectname from the datatable.(Eg. if we have two rows with same projectname,the datatable should be loaded with the only one row and neglect the other one.).I have been using webservices which has the datatable.
I want to achieve this functionality using linq.
I have pasted my code for datatable.Pls help me with working code.
[WebMethod]
public DataTable Get()
{
int a = 0;
cmd = con.CreateCommand();
con.Open();
cmd = con.CreateCommand();
cmd.CommandText = " Select PROJECTNAME,COMPANY,PROJECTSTATUS,STARTEDIN,COMPLETEDIN FROM CMPPROJECT WHERE STATUS ='" + a + "'";
using (OracleDataAdapter sda = new OracleDataAdapter())
{
cmd.Connection = con;
sda.SelectCommand = cmd;
using (DataTable dt = new DataTable())
{
dt.TableName = "CMPPROJECT";
sda.Fill(dt);
return dt;
}
}
}
You can create a DataView object which has a method ToTable in which you can pass true to parameter distinct to select distinct rows. But this has no sense to me. I would do this directly in a select query:
DataTable d = new DataTable("CMPPROJECT");
d.Columns.Add("PROJECTNAME");
d.Columns.Add("COMPANY");
d.Rows.Add(1, 1);
d.Rows.Add(1, 1);
d.Rows.Add(2, 2);
d = new DataView(d).ToTable("CMPPROJECT", true, "PROJECTNAME", "COMPANY");
Here is `linq solution:
var select = (from a in d.AsEnumerable()
select new { c1 = a["PROJECTNAME"], c2 = a["COMPANY"] }).Distinct().ToList();
d.Clear();
foreach (var item in select)
d.Rows.Add(item.c1, item.c2);

Editable gridview based on list

Is it possible to create a gridview based on a list? I have the following list:
ID = 1
Name = John
Zip = 33141
ID = 2
Name = Tim
Zip = 33139
I want to be able to create an editable gridview with this list
When i bind it to the grid view, it seems to put everyting in one column, and i can't figure out how to get it to seperate it into different columns
Here is my code for setting the DataSource of the GridView:
DataTable table = ConvertListToDataTable(personList);
GridView1.DataSource = table;
GridView1.DataBind();
static DataTable ConvertListToDataTable(List<string> list)
{
// New table.
DataTable table = new DataTable();
// Get max columns.
int columns = 7;
// Add columns.
for (int i = 0; i < columns; i++)
{
table.Columns.Add();
}
// Add rows.
foreach (var rd in list)
{
table.Rows.Add(rd);
}
return table;
}
Here is an example:
private class Person
{
int m_iID;
string m_sName;
string m_sZip;
public int ID { get { return m_iID; } }
public string Name { get { return m_sName; } }
public string Zip { get { return m_sZip; } }
public Person(int iID, string sName, string sZip)
{
m_iID = iID;
m_sName = sName;
m_sZip = sZip;
}
}
private List<Person> m_People;
private void ConvertListToDataTable(List<Person> People)
{
DataTable table = new DataTable();
DataColumn col1 = new DataColumn("ID");
DataColumn col2 = new DataColumn("Name");
DataColumn col3 = new DataColumn("Zip");
col1.DataType = System.Type.GetType("System.String");
col2.DataType = System.Type.GetType("System.String");
col3.DataType = System.Type.GetType("System.String");
table.Columns.Add(col1);
table.Columns.Add(col2);
table.Columns.Add(col3);
foreach (Person person in People)
{
DataRow row = table.NewRow();
row[col1] = person.ID;
row[col2] = person.Name;
row[col3] = person.Zip;
table.Rows.Add(row);
}
GridView1.DataSource = table;
GridView1.DataBind();
}

Resources