Wednesday, December 19, 2007
Fixing Derby Driver error in NetBeans 6.0
Wednesday, December 12, 2007
Custom Paging Helper Class
Tuesday, December 11, 2007
Getting the output parameter after executing your stored procedure.
If you have a stored procedure that has an OUTPUT parameter it, it requires different syntax to execute and check the output parameter when you are using Query Analyzer or SQL Management Studio. Let's assume you have a very simple stored procedure that select 5 rows and just returns the number of rows in a table as an output parameter. create PROCEDURE [dbo].GetRows @RowCount int OUTPUT AS select top 5 * from Person select @RowCount = count(1) from Person GO Here is the syntax to test it from Query Analyzer or SQL Management Studio. Declare @TotalCount int exec GetRows @TotalCount OUTPUT select @TotalCount If you want to do this from ADO.Net, here is the syntax. Once again, there is a trick. You must close the reader before checking the value of the output parameter. In this example we are using a SQL Helper class similar to one of the early MS DAAB and custom objects, but this is not the important piece of code. The important thing here is that when using a reader, you must close the reader before accessing the output parameter. If you use a DataAdapter to load results into a heavy like DataTable or DataSet. public List<PersonEntity> FetchRows(out int rowCount) { SqlDataReader reader = null; List<PersonEntity> entities = new List<PersonEntity>();
try { _sqlServer = new SqlServer(_sqlConnStr);
SqlParameter[] parameters = new SqlParameter[1]; parameters[0] = _sqlServer.MakeOutParam("@RowCount", SqlDbType.Int, -1);
reader = _sqlServer.ExecuteReader("GetRows", parameters);
while (reader.Read()) { entities.Add(FillEntityFromReader(reader)); }
// we must close the reader before we can read an output parameter reader.Close(); rowCount= (int)parameters[3].Value;
} catch (Exception ex) { throw ex; } finally { // a little overkill, but just for clarity, close everything explicitly if (reader != null && !reader.IsClosed) { reader.Close(); }
if (_sqlServer != null) { _sqlServer.Close(); _sqlServer.Dispose(); } }
return entities; } To call this method from C#, you would do something like: int count; FetchRows(out count); // use count here
Friday, December 7, 2007
Sorting and paging in SQL 2005 the easy and efficient way
GetPersonPage2005 3, 6, 'SEARCH_CODE ASC'
or to sort by SEARCH_CODE in Descending Order: GetPersonPage2005 3, 6, 'SEARCH_CODE DESC'
Thursday, December 6, 2007
Refresh Schema on GridView doesn't work with Custom Objects
Make your FormView handle nulls better
public
class PersonEntity { protected int? _personID; protected string _firstName; protected string _lastName; protected string _street1; protected string _street2; protected string _city; protected string _state; protected string _zipCode; protected string _createdBy; protected DateTime? _createdDate; protected int? _age; protected int? _height; protected int? _weight; // NOTE: Properties that expose these member variables have been removed to reduce clutter. }I have a DAL object that actually does all the CRUD operations on the entity. Here is a the method that is used when I need the load the data.
protected PersonEntity FillEntityFromReader(SqlDataReader reader) { PersonEntity entity = null;
try { if (reader != null && !reader.IsClosed) { entity = new PersonEntity(); entity.PersonID = reader[0] as int?; entity.FirstName = reader[1] as string; entity.LastName = reader[2] as string; entity.Street1 = reader[3] as string; entity.Street2 = reader[4] as string; entity.City = reader[5] as string; entity.State = reader[6] as string; entity.ZipCode = reader[7] as string; entity.CreatedBy = reader[8] as string; entity.CreatedDate = reader[9] as DateTime?; entity.Age = reader[10] as int?; entity.Height = reader[11] as int?; entity.Weight = reader[12] as int?; } } catch (Exception ex) { throw ex; }
return entity; } Here is how I check the properties for null so I know whether to convert the parameter to DBNull or not when I am doing update or insert operations. I have just pasted a some example for different data types. I am using customized version of the MS DAAB. In my version the last parameter is what determines if the DAAB inserts DBNull or the value passed. You'll notice string is different animal. It already can be null and does not use the HasValue, instead it uses string.IsNullOrEmpty() method. parameters[1] = _sqlServer.MakeInParam("@FirstName", System.Data.SqlDbType.NVarChar, 50, entity.FirstName, string.IsNullOrEmpty(entity.FirstName)); parameters[9] = _sqlServer.MakeInParam("@CreatedDate", System.Data.SqlDbType.DateTime, 0, entity.CreatedDate, !entity.CreatedDate.HasValue); parameters[10] = _sqlServer.MakeInParam("@Age", System.Data.SqlDbType.Int, 0, entity.Age, !entity.Age.HasValue);
Tuesday, December 4, 2007
ADO.NET performance unleashed
Custom Objects | Doodads | DataTable | DataSet | |
Average | 1403 | 2075 | 1771 | 1825 |
Minimum | 1083 | 1563 | 1447 | 1471 |
Maximum | 2717 | 7146 | 3325 | 2909 |
Standard Deviation | 298 | 721 | 227 | 233 |
As you might expect DataReader is the best performer when loading 6 records into array of entities. The standard deviation is even the least which means less volitility. .Net does not give an API to determine how much memory each class uses, but I used Red Gate Ants profiling tool to see that the number of objects created by DataTable and DataSet is MUCH greater than a Custom Object. This was not a surprise to me since DataTable and DataSet have much more functionility for tracking changes, etc than my Custom Object has. This is important when caching data.
Custom Objects | Doodads | DataTable | DataSet | |
Average | 1374 | 1988 | 1833 | 1841 |
Minimum | 1179 | 1700 | 1594 | 1644 |
Maximum | 2174 | 4986 | 2780 | 2937 |
Standard Deviation | 177 | 364 | 209 | 186 |
Below you can see that Custom Objects out performs the other Methods in nearly all cases. The gap increases between Custom Objects and the other methods now that we are loading multiple records. You can see at the end of the tests the graph becomes more volatile. I believe this is because of contention for the connections. At that point, we are starting to run out of connections and waiting is starting to occur. Some of the spikes are most likely due to garbage collection and memory allocation, but I can't prove that theory. These tests are performed in a loop that loops for 100 times, so garbage collection is sure play a part.
The big picture While Custom Objects are the best performer in general, its limited feature set may require more features be added or a framework be used that supplies the additional functionality. It is important to remember that the biggest bottleneck on most websites is database connectivity. This is fairly obvious in my opinion, but can also be seen if you profile your existing application (no matter how you connect to the database) the slowests methods will be the ones that connect to the database. It makes sense to spend your time optimizing here. It is important to remember that the best way to optimize database connectivity is to limit the times it is executed. One way to do this is to cache results, perhaps use ViewState and only load data on page load the first time, cache pages, etc. This is the largest reward. However, this is not always an option. In those cases, it is good to know which method here is going to give you the best performance. References These references more or less mirror what I am saying, and also provide some other solutions that may be helpful in some cases. If you have long queries and lots of users, you may want to keep those worker threads free by using Asynchronoous queries against the database. http://msdn.microsoft.com/msdnmag/issues/07/03/WickedCode/ Are you scared of using ViewState, this article may change your mind (if you're using ASP.Net 2.0 or greater). http://msdn.microsoft.com/msdnmag/issues/04/10/ViewState/ This article does a similar comparison to what I did, but focuses on Requests per second and Response time when the application is put under different loads. This comes to very similar conclusions, but from a different angle. http://msdn2.microsoft.com/en-us/library/ms978388.aspx More of the same, but also takes OLEDB into account. Think twice before using OLEDB. http://www.devx.com/vb2themax/Article/19887/1954?pf=true
Best Practices from TechEd http://www.theserverside.net/news/thread.tss?thread_id=26210