user4562396
user4562396

Reputation: 25

Save order data to local database

I am using C# to create a Windows form application. How do I create a local database table to save the data described below? Currently my data table consists of the columns of "inv_Id", "Item_Id" and "quantity". I know I need to create the columns to store each of the data items below, but I do not know how to structure the table.

I am new at C#. I did a search for this, and found things like e.g.https://www.youtube.com/watch?v=I5qvyyhUKfY

The data is shown in a list box and looks like:

Ordered Item:chair Price:$5.00
Ordered Item:table Price:$10.00
Ordered Item:pen Price:$2.00
Ordered Item:thumbdrive Price:$48.00

Subtotal:$65.00 Tax:$3.90 Total:$68.90

The purpose for me is to create the invoice then save it in the database after calculating everything.

Here is the code that I get the data load the data from db into drop down list (for user to select which item they want to buy), then (cust selected item will be listed in the listOuput box for calculating) user will select the item, then list box will show the selected output and calculate the total like a receipt.

After calculating, I wish to store all the data at the listOutput box to my db, but I having problem here.

Problem: I do not know how to move all my data from list box to database, and link them together in the structure.

public partial class Select_Item : Form
{
    SqlConnection con = new SqlConnection( @"Data Source=(LocalDB)\v11.0;AttachDbFilename=C:\Users\oo\Documents\Data.mdf;Integrated Security=True;Connect Timeout=30");
    SqlDataAdapter da = new SqlDataAdapter();
    DataTable dt = new DataTable();

    public struct Orders
    {
        public string item;
        public double price;           
    }

    const double TAX=0.06;
    Orders order = new Orders();
    static double subtotal=0;
    static double totalTaxes=0;  
    static double total;
    string finalBill = "FINAL BILL: \n";

    public Select_Item()
    {
        InitializeComponent();       
    }

    private void getValues(string custOrder)
    {          
        order.item = custOrder;

        String a = comboBox1.Text;
        order.price = Convert.ToDouble(custOrder);
        listOutput.Items.Add("Price: " + order.price);

        finalBill += "Ordered Item: " + a + "\nPrice: " + order.price.ToString("C2") + "\n";
        updateBill();           
    }

    private void updateBill()
    {
        subtotal += order.price;
        total += order.price + (order.price * TAX);
        totalTaxes += order.price * TAX;
        listOutput.Items.Clear();
        listOutput.Items.AddRange(finalBill.Split('\n'));
        listOutput.Items.Add("Subtotal:" + subtotal.ToString("C2"));
        listOutput.Items.Add("Tax:" + totalTaxes.ToString("C2"));
        listOutput.Items.Add("Total:" + total.ToString("C2"));
    }
    private void dropdownSelection(object sender, EventArgs e)
    {
       if (sender == comboBox1)
        System.Diagnostics.Debug.WriteLine("test " + comboBox1.SelectedValue.ToString());     
        getValues(comboBox1.SelectedValue.ToString());  
    }

Edited Code:

 private void StoreData()
        {
            int invoiceID;


            using (var con1 = new SqlConnection(@"Data Source=(LocalDB)\v11.0;AttachDbFilename=C:\Users\choo\Documents\Data.mdf;Integrated Security=True;Connect Timeout=30"))
            {
                con.Close();
                con.Open();
                using (var cmd = con.CreateCommand())
                {
                    cmd.CommandText = @"insert into Invoice(subtotal,tax,total) values (@subtotal,@tax,@total); select SCOPE_IDENTITY() as InvoiceID;";
                    cmd.Parameters.AddWithValue("@subtotal", subtotal);
                    cmd.Parameters.AddWithValue("@tax", tax);
                    cmd.Parameters.AddWithValue("@total", total);
                    using (var reader = cmd.ExecuteReader())
                    {
                        if (reader.Read())

                            invoiceID = (int)reader["InvoiceID"];

                    }
                }
                foreach (var item in OrderItems.Rows)
                {
                    using (var cmd = con.CreateCommand())
                    {

                        cmd.CommandText = @"insert into InvoiceItem(invoiceID,Item_Id,quantity) values (@invoiceID,@Item_Id,@quantity);";
                       // cmd.Parameters.AddWithValue("@InvoiceID", invoiceID);
                        cmd.Parameters.AddWithValue("@invoiceID", Convert.ToInt32("invoiceID"));
                        cmd.Parameters.AddWithValue("@Item_Id", Convert.ToInt32("Item_Id"));
                        cmd.Parameters.AddWithValue("@quantity", Convert.ToInt32("quantity"));
                        cmd.ExecuteNonQuery();



                    }
                }
            }
        }

Upvotes: 1

Views: 2347

Answers (1)

Esoteric Screen Name
Esoteric Screen Name

Reputation: 6112

I am assuming you are saving the data to an SQL database. Your invoice and item tables share a many to many relationship, so you should use a third table to link them together.

  • Invoice: invoiceID, subtotal, tax, total
  • Item: itemID, price
  • InvoiceItem: invoiceItemID, invoiceID, itemID, quantity

The InvoiceItem table has foreign keys to the other two. This way you keep your invoice and item data separate and clean; there's no mucking about with 10 different "pen" items because 10 different orders included a pen.

Note that you can calculate Invoice.subtotal by selecting all the items from that invoice and calculating the sum of quantity * price. I recommend including it on the Invoice table for convenience's sake.

To get the order into the database, you want something like this:

private void StoreData()
{
  int invoiceID;
  using(var con = new SqlConnection( @"Data Source=(LocalDB)\v11.0;AttachDbFilename=C:\Users\oo\Documents\Data.mdf;Integrated Security=True;Connect Timeout=30"))
  {
    con.Open();
    using(var cmd = con.CreateCommand())
    {
      cmd.CommandText = @"insert into Invoice(subtotal,tax,total) values (@subtotal,@tax,@total); select SCOPE_IDENTITY() as InvoiceID;";
      cmd.Parameters.AddWithValue("@subtotal",subtotal);
      cmd.Parameters.AddWithValue("@tax",tax);
      cmd.Parameters.AddWithValue("@total",total);
      using(var reader = cmd.ExecuteReader())
      {
        if(reader.Read())
          invoiceID = cmd.GetInt32("InvoiceID");
      }
    }
    foreach(var item in orderItems)
    {
      using(var cmd = con.CreateCommand())
      {
        cmd.CommandText = @"insert into InvoiceItem(InvoiceID,ItemID,quantity) values (@InvoiceID,@ItemID,@quantity);";
        cmd.Parameters.AddWithValue("@InvoiceID",invoiceID);
        cmd.Parameters.AddWithValue("@ItemID",item.ItemID);
        cmd.Parameters.AddWithValue("@quantity",item.Quantity);
        cmd.ExecuteNonQuery();
      }
    }
  }
}

Please understand this is a rudimentary, bare-bones idea of what you need to do. I've also written it without actually checking it in an IDE, so there might be a mistake or two. Importantly, it's not compatible with your existing code. Here's what you need to do to work this in:

  • Create a collection of items for your order, called orderItems. Each item in this collection should be some kind of object that represents a line in your ListBox. Note that your OrderItems struct is not sufficient to represent a single item (can you tell why?). Right now you're passing things around as strings of data. You need to be working with genuine objects to get a handle on the power of OOP.
  • Remove the SqlConnection declaration at the top of your form. You don't want connection objects just sitting around. The using blocks ensure a limited lifetime and that the object gets closed and disposed of properly. If you're using this object elsewhere (e.g. to get a list of items to show your user), then you need to modify that code to use this pattern.
  • Determining a good way to get itemID, subtotal, tax and total into this method. You could pass them as parameters, or you could use objects.

There are a lot of improvements that can be made, both to the code I've posted and to what you have already. This is meant only to be enough for basic functionality. Here are things that I leave to you as an exercise, but which you should do:

  • Error handling
  • Creating a proper collection of item objects and binding it to your UI elements
  • Getting static data like price and itemID from item objects and not out of the UI elements (ComboBox and ListBox)
  • Getting more familiar with the database interaction functionality, so you can understand how it works

Upvotes: 1

Related Questions