|
Using a Collection-Based Class
|
|
As reviewed above, before using a regular class to
manipulate a database, you should first create a class. To do this, you must
know the structure of the table that will be represented by the class. This
means that you should be familiar with the tables in the data set object.
After creating the class, to get the values from a table, you can declare a
variable from a collection-based class. Then, you can use the properties and
methods of the collection class.
|
Practical
Learning: Using a Collection-Based Class
|
|
- In the Solution Explorer, right-click CollegeParkAutoParts2 -> Add
-> Class...
- Set the name to AutoPart and press Enter
- Create a class as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CollegeParkAutoParts2
{
public class AutoPart
{
public int PartNumber { get; set; }
public int CarYear { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public string Category { get; set; }
public string PartName { get; set; }
public double UnitPrice { get; set; }
}
}
- Display the Part Editor form and double-click an empty area of its
body
- Implement the event as follows:
internal void ResetPartEditor()
{
cbxYears.Items.Clear();
cbxMakes.Items.Clear();
cbxModels.Items.Clear();
cbxCategories.Items.Clear();
cbxYears.Text = "";
cbxMakes.Text = "";
cbxModels.Text = "";
cbxCategories.Text = "";
txtPartName.Text = "";
txtUnitPrice.Text = "0.00";
Random rndNumber = new Random();
txtPartNumber.Text = rndNumber.Next(100001, 999999).ToString();
// Put the years in the top combo box
// Start with next year down to 1960
for (int i = DateTime.Today.Year + 1; i >= 1960; i--)
cbxYears.Items.Add(i.ToString());
// Prepare a data set object for the parts
DataSet dsParts = new DataSet("PartsSet");
// Establish a connection to the database
using (SqlConnection scCollegeParkAutoParts =
new SqlConnection("Data Source=(local);" +
"Database=CollegeParkAutoParts1;" +
"Integrated Security=SSPI;"))
{
// Create a command that will select the parts
SqlCommand cmdParts =
new SqlCommand("SELECT PartNumber, " +
" CarYear, " +
" Make, " +
" Model, " +
" Category, " +
" PartName, " +
" UnitPrice " +
"FROM Inventory.AutoParts;", scCollegeParkAutoParts);
cmdParts.CommandType = CommandType.Text;
// Open the connection
scCollegeParkAutoParts.Open();
// Create a data adapter that will get the values from the table
SqlDataAdapter sdaParts = new SqlDataAdapter(cmdParts);
// Store those values in the data set
sdaParts.Fill(dsParts);
// Create an auto part object
AutoPart StoreItem = null;
// Create an empty list of auto parts
List<AutoPart> lstAutoParts = new List<AutoPart>();
// Check each record from the (only) table in the data set
foreach (DataRow row in dsParts.Tables[0].Rows)
{
// Use the auto part object ...
StoreItem = new AutoPart();
// ... to create a record object
StoreItem.PartNumber = int.Parse(row[0].ToString());
StoreItem.CarYear = int.Parse(row[1].ToString());
StoreItem.Make = row[2].ToString();
StoreItem.Model = row[3].ToString();
StoreItem.Category = row[4].ToString();
StoreItem.PartName = row[5].ToString();
StoreItem.UnitPrice = double.Parse(row[6].ToString());
// Once the record is ready, store it in the collection variable
lstAutoParts.Add(StoreItem);
}
// To avoid duplicate values in the combo boxes,
// we will use collection classes
List<string> lstMakes = new List<string>();
List<string> lstCategories = new List<string>();
// Check the list of makes
foreach (AutoPart part in lstAutoParts)
{
// If the list doesn't yet contain the make, add it
if (!lstMakes.Contains(part.Make))
lstMakes.Add(part.Make);
}
// Once we have the list of makes,
// put them in the Make combo box
foreach (string strMake in lstMakes)
cbxMakes.Items.Add(strMake);
foreach (AutoPart part in lstAutoParts)
{
if (!lstCategories.Contains(part.Category))
lstCategories.Add(part.Category);
}
foreach (string strCategory in lstCategories)
cbxCategories.Items.Add(strCategory);
}
}
private void PartEditor_Load(object sender, EventArgs e)
{
ResetPartEditor();
}
- Call the ResetPartEditor() method before the closing curly bracket
of the Click event of the Submit button:
private void btnSubmit_Click(object sender, EventArgs e)
{
. . . No Change
ResetPartEditor();
}
- Return to the Part Editor form and double-click the Year combo box
- Implement the event as follows:
private void cbxYears_SelectedIndexChanged(object sender, EventArgs e)
{
// If the user was working on a previous part, cancel it
cbxModels.Items.Clear();
}
- Return to the Part Editor form and double-click the Make combo box
- Implement its event as follows:
private void cbxMakes_SelectedIndexChanged(object sender, EventArgs e)
{
// Create a data set of parts
DataSet dsParts = new DataSet("PartsSet");
// Establish a connection to the database
using (SqlConnection scCollegeParkAutoParts =
new SqlConnection("Data Source=(local);" +
"Database=CollegeParkAutoParts1;" +
"Integrated Security=SSPI;"))
{
// Create a command that will select the parts
SqlCommand cmdParts =
new SqlCommand("SELECT PartNumber, " +
" CarYear, " +
" Make, " +
" Model, " +
" Category, " +
" PartName, " +
" UnitPrice " +
"FROM Inventory.AutoParts;", scCollegeParkAutoParts);
// Open the connection
scCollegeParkAutoParts.Open();
// Create a data adapter that will get
// the record from the command
SqlDataAdapter sdaParts = new SqlDataAdapter(cmdParts);
// Store those records in the data set
sdaParts.Fill(dsParts);
// Create an empty object that can receive one record
AutoPart StoreItem = null;
// Create an empty list that can receive a list of records
List<AutoPart> lstAutoParts = new List<AutoPart>();
// Check each record
foreach (DataRow row in dsParts.Tables[0].Rows)
{
// Get the values of the current record
StoreItem = new AutoPart();
// Store the values in the object
StoreItem.PartNumber = int.Parse(row[0].ToString());
StoreItem.CarYear = int.Parse(row[1].ToString());
StoreItem.Make = row[2].ToString();
StoreItem.Model = row[3].ToString();
StoreItem.Category = row[4].ToString();
StoreItem.PartName = row[5].ToString();
StoreItem.UnitPrice = double.Parse(row[6].ToString());
// Once the record is ready, store it in the collection
lstAutoParts.Add(StoreItem);
}
// This will hold the list of parts
List<string> lstModels = new List<string>();
foreach (AutoPart part in lstAutoParts)
{
if ((part.CarYear == int.Parse(cbxYears.Text)) &&
(part.Make == cbxMakes.Text))
{
if (!lstModels.Contains(part.Model))
lstModels.Add(part.Model);
}
}
foreach (string strModel in lstModels)
cbxModels.Items.Add(strModel);
}
}
- Access the College Park Auto-Parts form and double-click
anunoccupied area of its body
- Implement the event as follows:
internal void ShowAutoParts()
{
tvwAutoParts.Nodes.Clear();
TreeNode nodRoot =
tvwAutoParts.Nodes.Add("College Park Auto-Parts",
"College Park Auto-Parts", 0, 1);
// Show the years nodes
for (int years = DateTime.Today.Year + 1; years >= 1960; years--)
nodRoot.Nodes.Add(years.ToString(), years.ToString(), 2, 3);
tvwAutoParts.SelectedNode = nodRoot;
// Expand the root node
tvwAutoParts.ExpandAll();
// Create an empty data set
DataSet dsParts = new DataSet("PartsSet");
// Create a connection to the database
using (SqlConnection scCollegeParkAutoParts =
new SqlConnection("Data Source=(local);" +
"Database=CollegeParkAutoParts1;" +
"Integrated Security=SSPI;"))
{
// Use a command to specify what action we want to take
SqlCommand cmdParts =
new SqlCommand("SELECT PartNumber, " +
" CarYear, " +
" Make, " +
" Model, " +
" Category, " +
" PartName, " +
" UnitPrice " +
"FROM Inventory.AutoParts;", scCollegeParkAutoParts);
// Open the connection
scCollegeParkAutoParts.Open();
// Use a data adapter to retrieve the values from the command
SqlDataAdapter sdaParts = new SqlDataAdapter(cmdParts);
// Fill the data set with the values from the data adapater
sdaParts.Fill(dsParts);
// Prepare a variable from the class we will use
AutoPart StoreItem = null;
// Create a collection
List<AutoPart> lstAutoParts = new List<AutoPart>();
// Check each record from the table from the data set
foreach (DataRow row in dsParts.Tables[0].Rows)
{
// Identify each record as a value of our class
StoreItem = new AutoPart();
// Get the values of the record and put them in the class
StoreItem.PartNumber = int.Parse(row[0].ToString());
StoreItem.CarYear = int.Parse(row[1].ToString());
StoreItem.Make = row[2].ToString();
StoreItem.Model = row[3].ToString();
StoreItem.Category = row[4].ToString();
StoreItem.PartName = row[5].ToString();
StoreItem.UnitPrice = double.Parse(row[6].ToString());
// Store the record in the collection
lstAutoParts.Add(StoreItem);
}
// Now that we have the records,
// we can use them as a normal collection
foreach (TreeNode nodYear in nodRoot.Nodes)
{
List<string> lstMakes = new List<string>();
foreach (AutoPart part in lstAutoParts)
{
if (nodYear.Text == part.CarYear.ToString())
{
if (!lstMakes.Contains(part.Make))
lstMakes.Add(part.Make);
}
}
foreach (string strMake in lstMakes)
nodYear.Nodes.Add(strMake, strMake, 4, 5);
}
foreach (TreeNode nodYear in nodRoot.Nodes)
{
foreach (TreeNode nodMake in nodYear.Nodes)
{
List<string> lstModels = new List<string>();
foreach (AutoPart part in lstAutoParts)
{
if ((nodYear.Text == part.CarYear.ToString()) &&
(nodMake.Text == part.Make))
{
if (!lstModels.Contains(part.Model))
lstModels.Add(part.Model);
}
}
foreach (string strModel in lstModels)
nodMake.Nodes.Add(strModel, strModel, 6, 7);
}
}
foreach (TreeNode nodYear in nodRoot.Nodes)
{
foreach (TreeNode nodMake in nodYear.Nodes)
{
foreach (TreeNode nodModel in nodMake.Nodes)
{
List<string> lstCategories = new List<string>();
foreach (AutoPart part in lstAutoParts)
{
if ((nodYear.Text == part.CarYear.ToString()) &&
(nodMake.Text == part.Make) &&
(nodModel.Text == part.Model))
{
if (!lstCategories.Contains(part.Category))
lstCategories.Add(part.Category);
}
}
foreach (string strCategory in lstCategories)
nodModel.Nodes.Add(strCategory, strCategory, 8, 9);
}
}
}
}
}
private void CollegeParkAutoParts_Load(object sender, EventArgs e)
{
ShowAutoParts();
}
- Return to the College Park Auto-Parts form and double-click the New
Auto Part button
- Implement the event as follows:
private void btnNewAutoPart_Click(object sender, EventArgs e)
{
PartEditor editor = new PartEditor();
if (editor.ShowDialog() == DialogResult.Cancel)
ShowAutoParts();
}
- Return to the College Park Auto-Parts form and click the tree view
- In the Properties window, click the Events button and, in the Events
section, double-click NodeMouseClick
- Implement the event as follows:
private void tvwAutoParts_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
TreeNode nodClicked = e.Node;
if (nodClicked.Level == 4)
lvwAutoParts.Items.Clear();
DataSet dsParts = new DataSet("PartsSet");
using (SqlConnection scCollegeParkAutoParts =
new SqlConnection("Data Source=(local);" +
"Database=CollegeParkAutoParts1;" +
"Integrated Security=SSPI;"))
{
SqlCommand cmdParts =
new SqlCommand("SELECT PartNumber, " +
" CarYear, " +
" Make, " +
" Model, " +
" Category, " +
" PartName, " +
" UnitPrice " +
"FROM Inventory.AutoParts;", scCollegeParkAutoParts);
scCollegeParkAutoParts.Open();
SqlDataAdapter sdaParts = new SqlDataAdapter(cmdParts);
sdaParts.Fill(dsParts);
AutoPart StoreItem = null;
List<AutoPart> lstAutoParts = new List<AutoPart>();
foreach (DataRow row in dsParts.Tables[0].Rows)
{
StoreItem = new AutoPart();
StoreItem.PartNumber = int.Parse(row[0].ToString());
StoreItem.CarYear = int.Parse(row[1].ToString());
StoreItem.Make = row[2].ToString();
StoreItem.Model = row[3].ToString();
StoreItem.Category = row[4].ToString();
StoreItem.PartName = row[5].ToString();
StoreItem.UnitPrice = double.Parse(row[6].ToString());
lstAutoParts.Add(StoreItem);
}
try
{
foreach (AutoPart part in lstAutoParts)
{
if ((part.Category == nodClicked.Text) &&
(part.Model == nodClicked.Parent.Text) &&
(part.Make == nodClicked.Parent.Parent.Text) &&
(part.CarYear.ToString() == nodClicked.Parent.Parent.Parent.Text))
{
ListViewItem lviAutoPart =
new ListViewItem(part.PartNumber.ToString());
lviAutoPart.SubItems.Add(part.PartName);
lviAutoPart.SubItems.Add(part.UnitPrice.ToString("F"));
lvwAutoParts.Items.Add(lviAutoPart);
}
}
}
catch (NullReferenceException)
{
}
}
}
- Return to the College Park Auto-Parts form and double-click the
Add/Select button
- Implement the event as follows:
private void btnAdd_Click(object sender, EventArgs e)
{
if (txtPartNumber.Text.Length == 0)
{
MessageBox.Show("There is no part to be added to the order.",
"College Park Auto-Parts",
MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
DataSet dsParts = new DataSet("PartsSet");
using (SqlConnection scCollegeParkAutoParts =
new SqlConnection("Data Source=(local);" +
"Database=CollegeParkAutoParts1;" +
"Integrated Security=SSPI;"))
{
SqlCommand cmdParts =
new SqlCommand("SELECT * FROM Inventory.AutoParts;", scCollegeParkAutoParts);
scCollegeParkAutoParts.Open();
SqlDataAdapter sdaParts = new SqlDataAdapter(cmdParts);
sdaParts.Fill(dsParts);
AutoPart StoreItem = null;
List<AutoPart> lstAutoParts = new List<AutoPart>();
foreach (DataRow row in dsParts.Tables[0].Rows)
{
StoreItem = new AutoPart();
StoreItem.PartNumber = int.Parse(row[0].ToString());
StoreItem.CarYear = int.Parse(row[1].ToString());
StoreItem.Make = row[2].ToString();
StoreItem.Model = row[3].ToString();
StoreItem.Category = row[4].ToString();
StoreItem.PartName = row[5].ToString();
StoreItem.UnitPrice = double.Parse(row[6].ToString());
lstAutoParts.Add(StoreItem);
}
foreach (AutoPart part in lstAutoParts)
{
if (part.PartNumber == int.Parse(txtPartNumber.Text))
{
ListViewItem lviSelectedPart =
new ListViewItem(part.PartNumber.ToString());
lviSelectedPart.SubItems.Add(part.PartName);
lviSelectedPart.SubItems.Add(part.UnitPrice.ToString());
lviSelectedPart.SubItems.Add(txtQuantity.Text);
lviSelectedPart.SubItems.Add(txtSubTotal.Text);
lvwSelectedParts.Items.Add(lviSelectedPart);
}
}
CalculateOrder();
}
}
- Return to the College Park Auto-Parts form and double-click the Save
Customer Order button
- Implement the event as follows:
private void btnSave_Click(object sender, EventArgs e)
{
if (lvwSelectedParts.Items.Count == 0)
return;
else
{
using (SqlConnection scAltairRealtors =
new SqlConnection("Data Source=(local);" +
"Database='CollegeParkAutoParts1';" +
"Integrated Security='SSPI';"))
{
SqlCommand cmdProperty =
new SqlCommand("INSERT INTO Transactions.CustomersOrders(ReceiptNumber, " +
"PartsTotal, TaxRate, TaxAmount, OrderTotal) VALUES(" + txtSave.Text + ", " +
txtPartsTotal.Text + ", " + txtTaxRate.Text + ", " +
txtTaxAmount.Text + ", " + txtOrderTotal.Text + ");",
scAltairRealtors);
scAltairRealtors.Open();
cmdProperty.ExecuteNonQuery();
}
// Check each selected part and get it ready to add to the table
// Each selected part of this order will have a common receipt #
for (int i = 0; i < lvwSelectedParts.Items.Count; i++)
{
using (SqlConnection cnnCustomerOrder =
new SqlConnection("Data Source=(local);" +
"Database=CollegeParkAutoParts1;" +
"Integrated Security=SSPI;"))
{
SqlCommand cmdCustomerOrder =
new SqlCommand("INSERT INTO Transactions.PartsSold(ReceiptNumber, PartNumber, PartName, " +
"UnitPrice, Quantity, SubTotal) VALUES(" + txtSave.Text + ", N'" +
lvwSelectedParts.Items[i].Text + "', '" +
lvwSelectedParts.Items[i].SubItems[1].Text + "', '" +
lvwSelectedParts.Items[i].SubItems[2].Text + "', '" +
lvwSelectedParts.Items[i].SubItems[3].Text + "', '" +
lvwSelectedParts.Items[i].SubItems[4].Text + "'); ", cnnCustomerOrder);
cnnCustomerOrder.Open();
cmdCustomerOrder.ExecuteNonQuery();
}
}
MessageBox.Show("The customer order has been saved.",
"College Park Auto-Parts",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
CollegeParkAutoParts_Load(sender, e);
}
- Change the Load event as follows:
private void SetReceiptNumber()
{
int iReceiptNumber = 0;
using (SqlConnection scCustomersOrders =
new SqlConnection(@"Data Source='CENTRAL\MSSQLSERVER2012';" +
"Database=CollegeParkAutoParts1;" +
"Integrated Security=SSPI;"))
{
SqlCommand cmdCustomersOrders =
new SqlCommand("SELECT ReceiptNumber " +
"FROM Transactions.CustomersOrders;", scCustomersOrders);
scCustomersOrders.Open();
SqlDataReader rdrCustomersOrders = cmdCustomersOrders.ExecuteReader();
while (rdrCustomersOrders.Read())
iReceiptNumber = int.Parse(rdrCustomersOrders[0].ToString());
}
txtSave.Text = (iReceiptNumber + 1).ToString();
}
private void CollegeParkAutoParts_Load(object sender, EventArgs e)
{
ShowAutoParts();
SetReceiptNumber();
lvwAutoParts.Items.Clear();
txtPartNumber.Text = "";
txtPartName.Text = "";
txtUnitPrice.Text = "0.00";
txtQuantity.Text = "0";
txtSubTotal.Text = "0.00";
lvwSelectedParts.Items.Clear();
txtPartsTotal.Text = "0.00";
txtTaxRate.Text = "5.75";
txtTaxAmount.Text = "0.00";
txtOrderTotal.Text = "0.00";
txtOpen.Text = "";
}
- Return to the College Park Auto-Parts form and double-click the Open
button
- Implement the event as follows:
private void btnOpen_Click(object sender, EventArgs e)
{
lvwSelectedParts.Items.Clear();
if (string.IsNullOrEmpty(txtOpen.Text))
return;
else
{
using (SqlConnection cnnCustomerOrder =
new SqlConnection("Data Source=(local);" +
"Database=CollegeParkAutoParts1;" +
"Integrated Security=SSPI;"))
{
SqlCommand cmdCustomerOrder =
new SqlCommand("SELECT * FROM Transactions.PartsSold " +
"WHERE ReceiptNumber = '" + txtOpen.Text + "';",
cnnCustomerOrder);
SqlDataAdapter sdaCustomerOrder =
new SqlDataAdapter(cmdCustomerOrder);
cnnCustomerOrder.Open();
DataSet dsCustomerOrder = new DataSet("PartsSoldSet");
sdaCustomerOrder.Fill(dsCustomerOrder);
for (int i = 0; i < dsCustomerOrder.Tables[0].Rows.Count; i++)
{
DataRow rowOrder = dsCustomerOrder.Tables[0].Rows[i];
ListViewItem lviOrder =
new ListViewItem(rowOrder["PartNumber"].ToString());
lviOrder.SubItems.Add(rowOrder["PartName"].ToString());
lviOrder.SubItems.Add(rowOrder["UnitPrice"].ToString());
lviOrder.SubItems.Add(rowOrder["Quantity"].ToString());
lviOrder.SubItems.Add(rowOrder["SubTotal"].ToString());
lvwSelectedParts.Items.Add(lviOrder);
}
}
using (SqlConnection cnnInvoice =
new SqlConnection("Data Source=(local);" +
"Database=CollegeParkAutoParts1;" +
"Integrated Security=SSPI;"))
{
string strInvoice = "SELECT ReceiptNumber, PartsTotal, TaxRate, " +
"TaxAmount, OrderTotal " +
"FROM Transactions.CustomersOrders " +
"WHERE ReceiptNumber = " + txtOpen.Text + ";";
SqlCommand cmdInvoice = new SqlCommand(strInvoice, cnnInvoice);
cnnInvoice.Open();
SqlDataReader rdrInvoice = cmdInvoice.ExecuteReader();
while (rdrInvoice.Read())
{
txtPartsTotal.Text = rdrInvoice[1].ToString();
txtTaxRate.Text = rdrInvoice[2].ToString();
txtTaxAmount.Text = rdrInvoice[3].ToString();
txtOrderTotal.Text = rdrInvoice[4].ToString();
}
}
}
}
- Return to the College Park Auto-Parts form and double-click the New
Customer button
- Implement the event as follows:
private void btnNewCustomerOrder_Click(object sender, EventArgs e)
{
ShowAutoParts();
lvwAutoParts.Items.Clear();
txtPartNumber.Text = "";
txtPartName.Text = "";
txtUnitPrice.Text = "0.00";
txtQuantity.Text = "0";
txtSubTotal.Text = "0.00";
lvwSelectedParts.Items.Clear();
txtPartsTotal.Text = "0.00";
txtTaxRate.Text = "5.75";
txtTaxAmount.Text = "0.00";
txtOrderTotal.Text = "0.00";
txtOpen.Text = "";
}
- Return to the College Park Auto-Parts form and double-click the
Close button
- Implement the event as follows:
private void btnClose_Click(object sender, EventArgs e)
{
Close();
}
- Execute the application
- Click the New Auto Part button and use
the Part Editor to
create
a few parts
- Create a few customers orders and save them
- Close the forms and return to your programming environment
- Execute the application again and open a previously saved order
- Close the forms and return to your programming environment
- Open the CollegeParkAutoParts3 database from this lesson
- Add a context menu for the Available Parts list view with the items:
Select, Edit..., and Delete

- Configure the context menu so that
- If the user clicks Select, the behavior would be the same as if
the user had double-clicked the item
- If the user clicks Edit..., the Part Editor dialog box would
display with the part in it. The user can then edit any part (year,
make, model, category, part name, or unit price) except the part
number. Then the user can save the changed part
- If the user clicks Delete, a message box would warn the user and
ask for confirmation with Yes/No answers. If the user clicks Yes,
the part would be deleted from the AutoParts table
- Configure the application so that the user can open an order, add
new parts to it, or delete parts from it, then save the order
- Extend the application so that the store can also sell items that
are, or are not, car-related, such as books, t-shirts, cleaning items,
maintenance items (steering oils, brake oils, etc), license plates, etc.
Every item in the store should have an item number. The user can enter
that item number in the Part # text box and press Tab or Enter. The
corresponding item would then be retrieved from the database and
displayed on the form. If there is no item with that number, a message
box should let the user know
|
|