tags:

views:

177

answers:

6

I'm trying to find optimal (fast vs easiest) way to access SQL Server code thru code in c#.

As i was learning from books I've encountered multiple suggestions usually telling me to do it via drag and drop. However since i wanted to do it in code first aproach was to get data by column numbers, but any reordering in SQL Query (like adding/removing columns) was pain for me to fix.

For example (don't laugh, some code is like 2 years old), i even coded special function to pass sqlQueryResult and check if it's null or not):

public static void exampleByColumnNumber(string varValue) {

        string preparedCommand = @"SELECT TOP 1 [SomeColumn],[SomeColumn2]

                                  FROM [Database].[dbo].[Table]
                  WHERE [SomeOtherColumn] = @varValue";
        SqlCommand sqlQuery = new SqlCommand(preparedCommand, Locale.sqlDataConnection);
        sqlQuery.Prepare();
        sqlQuery.Parameters.AddWithValue("@varValue) ", varValue);

        SqlDataReader sqlQueryResult = sqlQuery.ExecuteReader();
        if (sqlQueryResult != null) {
            while (sqlQueryResult.Read()) {
                string var1 = Locale.checkForNullReturnString(sqlQueryResult, 0);
            string var2 = Locale.checkForNullReturnString(sqlQueryResult, 1);
            }
            sqlQueryResult.Close();
        }
    }

Later on i found out it's possible thru column names (which seems easier to read with multiple columns and a lot of changing order etc):

    public static void exampleByColumnNames(string varValue) {

        string preparedCommand = @"SELECT TOP 1 [SomeColumn],[SomeColumn2]

                                  FROM [Database].[dbo].[Table]
                  WHERE [SomeOtherColumn] = @varValue";
        SqlCommand sqlQuery = new SqlCommand(preparedCommand, Locale.sqlDataConnection);
        sqlQuery.Prepare();
        sqlQuery.Parameters.AddWithValue("@varValue) ", varValue);

        SqlDataReader sqlQueryResult = sqlQuery.ExecuteReader();
        if (sqlQueryResult != null) {
            while (sqlQueryResult.Read()) {
                string var1 = (string) sqlQueryResult["SomeColumn"];
            string var2 = (string) sqlQueryResult["SomeColumn2"];
            }
            sqlQueryResult.Close();
        }
    }

And 3rd example is by doing it by column names but using .ToString() to make sure it's not null value, or by doing If/else on the null check.

    public static void exampleByColumnNamesAgain(string varValue) {

        string preparedCommand = @"SELECT TOP 1 [SomeColumn],[SomeColumn2], [SomeColumn3]

                                  FROM [Database].[dbo].[Table]
                  WHERE [SomeOtherColumn] = @varValue";
        SqlCommand sqlQuery = new SqlCommand(preparedCommand, Locale.sqlDataConnection);
        sqlQuery.Prepare();
        sqlQuery.Parameters.AddWithValue("@varValue) ", varValue);

        SqlDataReader sqlQueryResult = sqlQuery.ExecuteReader();
        if (sqlQueryResult != null) {
            while (sqlQueryResult.Read()) {
                string var1 = (string) sqlQueryResult["SomeColumn"].ToString();
            DateTime var2;
        DateTime.TryParse(sqlQueryResult["SomeColumn2"].ToString());

        int varInt = ((int) sqlQueryResult["SomeColumn3"] == null ? 0 : (int) sqlQueryResult["SomeColumn3"];

            }
            sqlQueryResult.Close();
        }
    }

Please bare in mind that I've just created this for sake of this example and there might be some typos or some slight syntax error, but the main question is which approach is best, which is the worst (i know first one is the one that i dislike the most).

I will soon have to start / rewrtiting some portion of my little 90k lines app which has at least those 3 examples used widely, so i would like to get best method for speed and preferably easiest to maintain (hopefully it will be same aproach).

Probably there are some better options out there so please share?

+6  A: 

It seems you may be looking at old books. If you're going to do it the "old fashioned way", then you should at least use using blocks. Summary:

using (var connection = new SqlConnection(connectionString))
{
    using (var command = new SqlCommand(commandString, connection))
    {
        using (var reader = command.ExecuteReader())
        {
             // Use the reader
        }
    }
}

Better still, look into Entity Framework.

Links: Data Developer Center

John Saunders
My question was more about using the proper way of column names vs column numbers vs different solutions. Why your code gave me some new tips it doesn't fully answer my original question :-)
MadBoy
@MadBoy: actually, the rest of my answer _does_ address your question. Use Entity Framework, and your question doesn't arise. You'll simply use strongly-typed properties: `var q = from c in context select c; foreach (var r in q) {// r.SomeColumn; r.SomeColumn2;}`
John Saunders
@John Saunders - +1 answer, but there is no need for all of the `{}` nests; you can stack the `using` lines and only have a single level of nesting. In a small example it's not really an issue (other that a choice of taste), but in a large block of code it can really help readability.
Stevo3000
Hmm, ... Entity Framework (or any other ORM for that matter), is not a silver bullet. I do agree that it is a very useful tool for certain problems, but I wouldn't call it 'the new way of working with data' (it's not even working with data, but with entities).Not all applications really need to translate a relational model to an object model.
Frederik Gheysels
@Frederik: I recommend Entity Framework as the "new DataSet"
John Saunders
Hmm ...When developing an application that has a lot of business logic, I would use an ORM like NHibernate or EF.When developing an application that is really data-centric, without much BL, I think I would use a dataset.
Frederik Gheysels
+2  A: 

If it's easy you're looking for, you can't do any better than Linq-to-SQL:-

http://weblogs.asp.net/scottgu/archive/2007/05/19/using-linq-to-sql-part-1.aspx

If your SQL database already exists, you can be up-and-running in seconds.

Otherwise, I agree with John.

Iain Galloway
Yes the database is already up and running and people are using my application. Just since i have to continue development (and improve it in places where I've last been year ago) i know the code has to be heavily rewritten in some places especially since i want it to be multithreaded.
MadBoy
You'll be up and running, but you'll be tied to the current structure of your database. LINQ to SQL always produces a one-to-one mapping between database tables and classes. If your database changes, then your classes will also have to change. Entity Framework solves that problem, and is also not limited to working with SQL Server.
John Saunders
Absolutely. On the other hand, EF has a *much* steeper learning curve. You'll be up and running in minutes rather than seconds :P
Iain Galloway
+2  A: 

you should have a look into these tutorials,

[http://www.asp.net/learn/data-access/][1]

All the work you are planning is already been done.

have a look at this way of doing same what you are doinng

  string preparedCommand =
  @"SELECT TOP 1 [SomeColumn],[SomeColumn2], [SomeColumn3]    
  FROM [Database].[dbo].[Table]
  WHERE [SomeOtherColumn] = @varValue";
  [1]: http://www.asp.net/learn/data-access/

More better way of doing the same above is by Using LINQ TO SQL

var result = from someObject in SomeTable
             where SomeColumnHasValue == ValueToCompare
             select new { SomeColumn, SomeColumn1, SomeColumn2};
  • No Type Safety Issues
  • Visualise Database in C# while you work on it
  • at compile time less errors
  • less code
  • more productive

Following are some of the great resources for LINQ if you are interested

Hope it helps

Asad Butt
Not sure what you mean by finishing it and using it myself. I've wrote it and it's working. But since i wrote it and been learning c#/sql at the very same time i imagine it has looooots of crappy code that sooner or later i would like to fix, especially since i need to add/improve some code here and there so i might aswell update some portions to newer better code.
MadBoy
"I will soon have to start / rewrtiting some portion of my little 90k lines app which has at least those 3 examples used widely", You are right, I did not get it at correct, I thought, you are about start working on it. Any way. Best Of Luck and hope you enjoy working with new Data Access Methods as you replace some of the bits from your old App.
Asad Butt
edited my answer.
Asad Butt
+1  A: 

If you're looking into using just straight ADO.net you might want to go out and find Microsoft's Enterprise Library's Data Access Application Block . David Hayden has a decent article that goes into some detail about using it.

Good luck and hope this helps some.

Chris
+1  A: 

The easiest way to do data access in C#, to my mind, is using typed DataSets. A lot of it really is drag-and-drop, and it's even easier in .NET 2.0+ than in .NET 1.0/1.1.

Have a look at this article, which talks about using typed DataSets and TableAdapters:

Building a DAL using Strongly Typed TableAdapters and DataTables in VS 2005 and ASP.NET 2.0

A typed DataSet is basically a container for your data. You use a TableAdapter to fill it (which happens with SQL or stored procs, whichever you prefer) and to update the data afterwards. The column names in each DataTables in your DataSet are autogenerated from the SQL used to fill them; and relations between database tables are mirrored by relations between DataTables in the DataSet.

Kyralessa
+1  A: 

Don't convert data to strings only to try to parse it; DataReaders have methods to convert SQL data to .Net data types:

using (var connection = new SqlConnection(Locale.sqlDataConnection))
using (var command = new SqlCommand(preparedCommand, connection))
using (var reader = command.ExecuteReader())
{
    int stringColumnOrdinal = reader.GetOrdinal("SomeColumn");
    int dateColumnOrdinal = reader.GetOrdinal("SomeColumn2");
    int nullableIntColumnOrdinal = reader.GetOrdinal("SomeColumn3");
    while (reader.Read())
    {
        string var1 = reader.GetString(stringColumnOrdinal);
        DateTime var2 = reader.GetDateTime(dateColumnOrdinal);
        int? var3 = reader.IsDBNull(nullableIntColumnOrdinal) ? null : reader.GetInt32(nullableIntColumnOrdinal);
    }
}
Dour High Arch
Thanks, it's useful.
MadBoy