Click here to Skip to main content
15,890,690 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi, I am creating a windows form application to store car stock.

This is my first 3 tier app: UI,CAR OBJECT,DATA ACCESS

My user interface has drop downs for: Make, Model,Colour,Year,Condition,Mileage.

I have sql tables for Make,Model,Colours.

I would like to know the correct way to return the Makes from the table and populate the dropdown - when the user selects a make E.g BMW it will filter the models from the model table and filter it by make and populate the model dropdown.

I would also like to know how to get the colours from the colour table. I.e does this all go in the data access layer or the business layer?

Thanks

Below is currently in the data Access layer, do I need to call this from business layer? Would this work to populate dropdowns and filter model by make?

C#
public DataSet RetrieveTableDS(string select, string table, string where)
       {
           DataSet ds = null;

           try
           {
               OpenConnection();

               string selectStr = "select " + select + " from " + table + " where " + where;

               SqlDataAdapter da =
               new SqlDataAdapter(selectStr, Conn);
               ds = new DataSet();
               da.Fill(ds, table);

               CloseConnection();

           }
           catch (Exception e)
           {

               throw new Exception(e.Message);

           }
           return ds;

       }
Posted
Updated 13-Nov-14 3:44am
v3
Comments
Richard Deeming 13-Nov-14 9:52am    
Don't write code like this - your method provides no means of passing parameters to the WHERE clause, so you're forcing yourself to write code which is vulnerable to SQL Injection[^].

NEVER use string concatenation to build a SQL query. ALWAYS use a parameterized query.

Yeah this can be used. You just need to pass the appropriate where condition with the MakeId.

So, your final query would look like...
SQL
Select ModelId, ModelName FROM Model WHERE MakeId = 1

MakeId should be a foreign key in Model Table. That means Model and Make Tables should have a relationship.

And yes, as Richard mentioned, your code is vulnerable to SQL Injection. Correct it.
 
Share this answer
 
v2
Member 11228069 wrote:
3 tier app: UI,CAR OBJECT,DATA ACCESS



Those are layers, not tiers -- layers are awesome.

Don't try to write one method that will perform all the data access; write a method for each operation that needs to be performed -- and use parameters to provide values to the statements.

Performance can be improved by reusing objects rather than throwing them out and recreating them. This, of course, assumes a system that does a lot of operations. It may not matter much in your current situation, but you could run into a situation in the future where it does matter, and developing good habits now will pay of later.

I recommend you not use DataAdapters, but if you do, remember that the adapter will open and close the Connection for you, so you needn't do that.

That catch is a very bad idea; not only does it not provide any benefit, it actually makes things worse. Either...
0) Simply remove the try/catch
1) Add some information to the Data property of the Exception -- e.Data [ "CommandText" ] = selectStr ;
and rethrow ; -- throw ;
2) If you want to throw a more informative Exception, then include the original Exception as the InnerException -- throw new UnableToFetchDataException(e.Message,e);
3) Both 1 and 2 (recommended)
 
Share this answer
 
v2
Comments
PIEBALDconsult 13-Nov-14 10:57am    
"add car, get colours, get makes, get models?"
Yes, there should be specific methods

"have one "read" method in data access and pass the different table names"
No.

"call these in the business layer (carObject) and then call those in the UI"
Yes.
Ok thanks for your help, here is my add method in the data access layer, does this look ok?

C#
public void Add(carObject carObj)
      {
          try
          {
              string addString = @"INSERT INTO cars (MAKE,MODEL,COLOUR,YEAR,MILEAGE,CONDITION) VALUES (@Make,@Model,@Colour,@Year,@Mileage,@Condition)";

              OpenConnection();


              SqlCommand cmd = new SqlCommand(addString, Conn);

              cmd.Parameters.AddWithValue("@Make", carObj.Make);
              cmd.Parameters.AddWithValue("@Model", carObj.Model);
              cmd.Parameters.AddWithValue("@Colour", carObj.Colour);
              cmd.Parameters.AddWithValue("@Year", carObj.Make);
              cmd.Parameters.AddWithValue("@Mileage", carObj.Mileage);
              cmd.Parameters.AddWithValue("@Condition", carObj.Condition);


              cmd.ExecuteNonQuery();
              cmd.Dispose();
              CloseConnection();
          }
          catch (Exception e)
          {
              throw new Exception(e.Message, e);
          }
      }


and I call this function from the business layer (carobject)

C#
public void addCarToDb()
     {
         carData.Add(this);

     }
 
Share this answer
 
v2
Comments
PIEBALDconsult 13-Nov-14 11:11am    
That looks much better, but please improve that catch some more.
You should not have posted this as an answer, though.
DHicks19 13-Nov-14 11:18am    
Sorry, new to CodeProject. Is this better?

catch (SqlException e)
{
e.Data.Add("Query", addString);
throw;
}


and just to verify, to retrieve the colours from colour table I just create a method specific for this in the data access layer and also add method in business layer, then call this on form load to populate dropdown?

Sorry, I am new to this. Appreciate your help.
PIEBALDconsult 13-Nov-14 12:07pm    
Yes, that looks better. And, yes, that sounds OK.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900