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
Saturday, December 1, 2007
Dynamic Sql Tricks
Saturday, November 17, 2007
Friday, November 16, 2007
Stopping form from submitting
Thursday, November 8, 2007
Query by date (no time) in SQL Server
This is a simple one. This technique can be used to search for rows where the MyDateColumn has the date specified (as a string) and the time doesn't matter. select * from MyTable where Convert(VARCHAR, MyDateColumn, 101) = '10/31/2007' It can also be used in the select statement to format the output of MyDateColumn without the time portion. select Convert(VARCHAR, MyDateColumn, 101) = '10/31/2007' from MyTable
Tuesday, November 6, 2007
Highlighting matches using Regular Expressions in C#
Friday, November 2, 2007
The coolest zip tool ever!
Opening up Scheduled Tasks for remote servers from the command line
Thursday, October 25, 2007
Getting to the result that was returned when selecting in an ObjectDataSource
protected
void BLL_Selected(object sender, ObjectDataSourceStatusEventArgs e) { DataTable dt = e.ReturnValue as DataTable; // do interesting stuff here... }Select distinct rows from a DataTable
It is probably best to describe a scenario to understand what I am trying to describe. Let's assume you have a DataTable called myDataTable that has three columns (Col1, Col2, Col3). You want to get a distinct list based on Col1 and Col2. In SQL you could do something like: Select distinct Col1, Col2 from MyTable; Believe it or not, we can do the same thing with the in memory table known as a DataTable in .Net. // populate the DataTable DataTable myDataTable = DAL.doSomeQuery();
bool distinct = true;
DataTable distinctRows = myDataTable.DefaultView.ToTable(distinct, new string[] { "Col1", "Col2" }); That is it, but it is only available in .Net 2.0.
Tuesday, October 23, 2007
ASP.NET and EventLog: Event ID issues when writing to Event Log
Literally you can copy and paste from one SQL Server to another
Easy way to restart your ASP.NET web site
Wednesday, October 10, 2007
Image alignment in HTML / CSS
<
img border="0" src="myImage.gif" style="vertical-align:middle"/>my text that is to the right of the image.
Finding column references in SQL Server
if exists (select * from dbo.sysobjects
where id = object_id(N'[dbo].[usp_FindColumnUsage]')
and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[usp_FindColumnUsage]
GO
CREATE PROCEDURE [dbo].[usp_FindColumnUsage] @vcTableName varchar(100), @vcColumnName varchar(100) AS /************************************************************************************************ DESCRIPTION: Creates prinatable report of all stored procedures, views, triggers and user-defined functions that reference the table/column passed into the proc. PARAMETERS: @vcTableName - table containing searched column @vcColumnName - column being searched for REMARKS: To print the output of this report in Query Analyzer/Management Studio select the execute mode to be file and you will be prompted for a file name to save as. Alternately you can select the execute mode to be text, run the query, set the focus on the results pane and then select File/Save from the menu.
This procedure must be installed in the database where it will be run due to it's use of database system tables.
USAGE: usp_FindColumnUsage 'jct_contract_element_card_sigs', 'contract_element_id' AUTHOR: Karen Gayda
DATE: 07/19/2007
MODIFICATION HISTORY: WHO DATE DESCRIPTION --- ---------- ------------------------------------------- *************************************************************************************************/ SET NOCOUNT ON
PRINT '' PRINT 'REPORT FOR DEPENDENCIES FOR TABLE/COLUMN:' PRINT '-----------------------------------------' PRINT @vcTableName + '.' +@vcColumnName
PRINT '' PRINT '' PRINT 'STORED PROCEDURES:' PRINT ''
SELECT DISTINCT SUBSTRING(o.NAME,1,60) AS [Procedure Name] FROM sysobjects o INNER JOIN syscomments c ON o.ID = c.ID WHERE o.XTYPE = 'P' AND c.Text LIKE '%' + @vcColumnName + '%' + @vcTableName + '%' ORDER BY [Procedure Name] PRINT CAST(@@ROWCOUNT as Varchar(5)) + ' dependent stored procedures for column "' + @vcTableName + '.' +@vcColumnName + '".'
PRINT'' PRINT'' PRINT 'VIEWS:' PRINT'' SELECT DISTINCT SUBSTRING(o.NAME,1,60) AS [View Name] FROM sysobjects o INNER JOIN syscomments c ON o.ID = c.ID WHERE o.XTYPE = 'V' AND c.Text LIKE '%' + @vcColumnName + '%' + @vcTableName + '%' ORDER BY [View Name] PRINT CAST(@@ROWCOUNT as Varchar(5)) + ' dependent views for column "' + @vcTableName + '.' +@vcColumnName + '".'
PRINT '' PRINT '' PRINT 'FUNCTIONS:' PRINT ''
SELECT DISTINCT SUBSTRING(o.NAME,1,60) AS [Function Name], CASE WHEN o.XTYPE = 'FN' THEN 'Scalar' WHEN o.XTYPE = 'IF' THEN 'Inline' WHEN o.XTYPE = 'TF' THEN 'Table' ELSE '?' END as [Function Type] FROM sysobjects o INNER JOIN syscomments c ON o.ID = c.ID WHERE o.XTYPE IN ('FN','IF','TF') AND c.Text LIKE '%' + @vcColumnName + '%' + @vcTableName + '%' ORDER BY [Function Name] PRINT CAST(@@ROWCOUNT as Varchar(5)) + ' dependent functions for column "' + @vcTableName + '.' +@vcColumnName + '".'
PRINT'' PRINT'' PRINT 'TRIGGERS:' PRINT''
SELECT DISTINCT SUBSTRING(o.NAME,1,60) AS [Trigger Name] FROM sysobjects o INNER JOIN syscomments c ON o.ID = c.ID WHERE o.XTYPE = 'TR' AND c.Text LIKE '%' + @vcColumnName + '%' + @vcTableName + '%' ORDER BY [Trigger Name] PRINT CAST(@@ROWCOUNT as Varchar(5)) + ' dependent triggers for column "' + @vcTableName + '.' +@vcColumnName + '".'
GO