0

I have a program where the user can add products to the system, and then search them by the product name. Everything is working fine, except at the moment is able to enter two products with the same name. I need the program to not allow this.

I have a method assigned to the 'Add' button, which saves the product name, customer name and firmware location to a text file. Here is that method:

    private void button_Click(object sender, RoutedEventArgs e)
    {
        bool found = false;
        string searchTerm = productNameTextBox.Text.ToUpper();


        if ((productNameTextBox.Text == "") || (customerNameTextBox.Text == "") || (firmwareLocationTextBox.Text == ""))
        {
            MessageBox.Show("Please fill in all the text boxes");

        }
        else if (Contains(searchTerm) == true)
        {
            MessageBox.Show("Product already added");
        }
        else
        {
                string inputCustomerName = customerNameTextBox.Text.ToUpper();
                string inputProductName = productNameTextBox.Text.ToUpper();
                string inputFirmwareLocation = firmwareLocationTextBox.Text;

                try
                {
                    Product newProduct = new Product(inputProductName, inputCustomerName, inputFirmwareLocation);
                    newProduct.Save("Products.txt");
                    File.AppendAllText("ProductNames.txt", inputProductName + Environment.NewLine);
                    MessageBox.Show("Product added");
                    emptyTheTextBoxes();

                }
                catch
                {
                    MessageBox.Show("Product could not be added");
                }
            }
       }

I have also made a method which will search a text file to see if the users product name has already been stored, and then return a Boolean. This is the method:

    public bool Contains (string searchTerm)
    {
        string line;
        bool found = false;


            System.IO.StreamReader file = new System.IO.StreamReader("ProductNames.txt");

            while ((line = file.ReadLine()) != null)
            {

                if (line.Contains(searchTerm))
                {
                    found = true;
                    break;
                }
            }


        if (found == true)
        {
            return true;
        }
        else
        {
            return false;
        }
        file.Close();
    }

When I try to save the input, a message box appears saying "Product could not be added". However, if I comment out the else if statement which calls the method, it works fine.

I thought it may be because I open the file when the method is called, and maybe it wasn't closing properly. So I added the 'file.Close()' and it hasn't made a difference. I feel like I've just made a silly mistake somewhere, but its been bugging me for hours! Definitely appreciate a fresh pair of eyes!

Thanks Lucy

lucycopp
  • 213
  • 1
  • 4
  • 18
  • modify your catch to catch the exception and then output the error message rather than "Product could not be added". That will tell you what's wrong. – sr28 Aug 17 '16 at 09:39
  • 2
    Change your `catch` to `catch (Exception ex)` and your `MessageBox.Show("..")` to `MessageBox.Show(ex.ToString())` and post the resulting text. Custom messages arnt helping. Exceptions are. @sr28 one second faster <. – C4d Aug 17 '16 at 09:39
  • @C4u - hehe, mine is less descriptive though. – sr28 Aug 17 '16 at 09:40
  • Will do - one moment – lucycopp Aug 17 '16 at 09:46
  • How do You think, is executed code after return? – Jacek Cz Aug 17 '16 at 09:46
  • It says it cannot access the file ProductNames.txt because it is being used by another process – lucycopp Aug 17 '16 at 09:48
  • 1
    Do you think that maybe the file isn't closing when the method is called? – lucycopp Aug 17 '16 at 09:48
  • Got it working now guys thank you! – lucycopp Aug 17 '16 at 09:52
  • I'm guessing it's because in your Contains() method your never closing the file as you return true or false before it closes it. However, post your answer. – sr28 Aug 17 '16 at 09:53

2 Answers2

1

In general I would suggest that you separate out your persistence of objects from your object/data management.

You are trying to read and write to the filesystem for the same file in different parts of the program and it seems like you are having an issue with the file not being released, probably because you didn't close it correctly.

You are trying to treat the file system as if it is a database, and this is probably not the best approach. There are of course use cases where this might be needed.

Instead I would suggest the following approach.

  1. During start up read the file. Load the products into a collection which you keep in memory.
  2. Allow your program to read, update, create, delete products in the collection.
  3. During shutdown (can also be triggered manually if you want), save your products onto disk.

This will allow you to avoid such issues. And also be quicker.

Optionally you could also then use something like HashSet<T> for your collection. This does not allow duplicate entries (remember to override equals and hashcode in your Product object). Then when trying to add to the collection if it returns false then it was not added, which would indicate a duplicate. So this might make it easier and quicker to check for you.

jason.kaisersmith
  • 8,712
  • 3
  • 29
  • 51
0

I had the file.close() in the wrong place. Here is where I moved it to:

 public bool Contains (string searchTerm)
    {
        string line;
        bool found = false;


            System.IO.StreamReader file = new System.IO.StreamReader("ProductNames.txt");

            while ((line = file.ReadLine()) != null)
            {

                if (line.Contains(searchTerm))
                {
                    found = true;
                    break;
                }
            }

        file.Close();


        if (found == true)
        {
            return true;

        }
        else
        {
            return false;
        }

    }
lucycopp
  • 213
  • 1
  • 4
  • 18
  • A few seconds before my comment :) – sr28 Aug 17 '16 at 09:53
  • Try the using statement with your StreamReader: https://msdn.microsoft.com/en-GB/library/yh598w02.aspx – sr28 Aug 17 '16 at 09:55
  • The original code *should* have been generating a CS0162 warning about unreachable code, which you completely failed to mention and (somehow) didn't think was relevant? – Damien_The_Unbeliever Aug 17 '16 at 10:19
  • Don't forget to Dispose of your StreamReader! http://stackoverflow.com/questions/1065168/does-disposing-streamreader-close-the-stream – Andez Aug 17 '16 at 12:04