Monday, December 13, 2010

SQL AZURE - A Warning to Those Using sys.dm_exec_query_stats

Today, I read Dinakar Nethi's blog post on Troubleshooting and Optimizing Queries with SQL Azure. In that article, he discusses how we can use SQL Azure DMVs to troubleshoot poor performing queries. He relies heavily on sys.dm_exec_query_stats DMV, which I use all the time with on-premise SQL Servers.

While reading it, I remembered reading a blog post from Adam Mechanic about how if there is an alter statement in a batch, sys.dm_exec_query_stats will not pick up any of the statements in the batch. This might be because some DDL statements do not generate query plans, but I'm not sure.

I wanted to see if SQL Azure had the same issue. I was hopeful it wouldn't because they change the implementation of many of their views. Nope...the issue is still there in SQL Azure. I re-wrote Adam's script, because SQL Azure does not support SELECT..INTO. Also, tables in SQL Azure require a primary key.

Here's the script:


--BATCH #1
--In this batch, the select does not appear in sys.dm_exec_query_stats

create table #x
(a int primary key
, b varchar(100))

--This is the alter statement that causes the issue.
alter table #x
add unique (a)

insert into #x
values
  
(1, 'getstuff')
, (
2, 'getMoreStuff')
, (
3, 'getEvenMoreStuff')

select *
from #x

select *
from sys.dm_exec_query_stats
where    plan_handle IN    
(        
select            plan_handle        
from sys.dm_exec_requests        
where            session_id = @@spid    )

drop table #x

GO

--BATCH #2
--In this batch, the select does appear in sys.dm_exec_query_stats,
--because I change the alter table to a create index statement

create table #x
(a int primary key
, b varchar(100))

--I change the alter statement to a create unique index statement.
CREATE UNIQUE INDEX whatever
ON #x (b)

insert into #x
values
  
(1, 'getstuff')
, (
2, 'getMoreStuff')
, (
3, 'getEvenMoreStuff')

select *
from #x

select *
from sys.dm_exec_query_stats
where    plan_handle IN    
(        
select            plan_handle        
from sys.dm_exec_requests        
where            session_id = @@spid    )

drop table #x

Sunday, December 5, 2010

Day Of Azure II Talk - SQL Azure Survey

Lynn and I had a blast speaking at the Day of Azure. We covered SQL Azure as thoroughly as possible in 2 hours. You could probably tell that we could have spent two days on our topic....maybe next time. Here are the slides:

Thursday, December 2, 2010

A Lap Around SQL Azure Data Sync - Step By Step Example

SQL Azure Data Sync is a cloud-based service, hosted on Microsoft SQL Azure, which allows many SQL Azure databases to stay consistent with one another. This capability is ideal for a project I’m currently working on where the users need low latency data access across an entire company but they are geographically separated by great distances with one office in USA and one in Europe. SQL Azure Data Sync allows them to have consistently synchronized data physically close to both locations.

SQL Azure Data Sync is super simple to setup (try saying that five times fast). In this article, I’ll show you how to implement a data synchronization between two databases on the same logical SQL Azure server. We’ll be implementing the design in the diagram below.




STEP 1 – Signup for SQL Azure
If you need some guidance on how to do that, follow this link:
SQL Azure Signup Tutorial

As of this writing (AOTW), Microsoft is literally giving SQL Azure away (Web Edition – 1GB), so you really have no excuse on why you haven’t signed up yet.

STEP 2 – Create Two Databases
OK, here’s where you might get charged. For this example, we’ll create two databases that will sync with each other, and you might get charged when you add the second database. When we're finished, you may want to delete one or both databases to keep costs down. Database usage is metered per day, so your bill should be less than $1, but I haven’t confirmed that.

You create a database by following these steps:

a) Go to http://sql.azure.com. Click on the project you created in Step 1.




b) First you’ll see just the Master database. That doesn’t do us much good, since SQL Azure doesn’t allow us to add tables to the Master Database.




We need two more databases. Click on “Create Database.” The dialog below will pop up. Type in library1, and click “Create.” Do the same for the library2 database.




When you are finished, your console should look like this:





Now you have two blank databases. Let’s add some schema and data to library1, then we'll configure SQL Azure Data Sync to copy them over to library2.

STEP 3 – Add Schema and Data to Library1.

We’ll use SQL Server Management Studio (SSMS) to add the schema and data, though we could have easily used Visual Studio, SQLCMD, or even BCP.

Connect to SQL Azure using your server name, user name, and password. Don’t worry, it’s all encrypted when connecting to SQL Azure. Make sure your internal firewall allows port 1433 to pass through to SQL Azure. AOTW, SQL Azure’s TCP port cannot be adjusted, so don’t bother trying to look up how to change it. It’s a tough break that network admins at many organizations unilaterally block that port.

Your SSMS connection dialog will look something like this:




Once you’re connected, run this script to create two tables. You’ll notice that the TITLES table references the AUTHORS table. That will be important later.


CREATE TABLE authors
(id INT PRIMARY KEY
, name VARCHAR(100) DEFAULT('')
)

CREATE TABLE titles
(id INT PRIMARY KEY
, name VARCHAR(100) DEFAULT(11)
,
authorId INT REFERENCES authors(id))

INSERT INTO authors
VALUES
  
('1', 'Stephen King')
, (
'2', 'George RR Martin')
, (
'3', 'Neal Stephenson')
, (
'4', 'Steig Larsson')


INSERT INTO titles
VALUES
  
('1', 'A Game of Thrones', '2')
, (
'2', 'A Clash of Kings', '2')
, (
'3', 'The Song of Susannah', '1')
, (
'4', 'The Gunslinger', '1')



There are a couple of things to notice about this script. One, each table in SQL Azure needs a clustered index. I’m creating one by specifying a primary key in the create table statement. AOTW, SQL Azure will allow you to create a table without a clustered index, but it won’t allow you to insert data into it, so there’s no reason to bother to even create the heap table. Two, I like the insert syntax where we can insert multiple rows after the VALUES keyword. That’s not SQL Azure specific, I just think it’s cool.

We have two databases, one filled with tables and data and one empty. Let’s fix that and get to the meat of this demo.

STEP 4 – Setup SQL Azure Data Sync.
a) Goto http://www.sqlazurelabs.com/ and click on “SQL Azure Data Sync”

b) You’ll need to sign in to Windows Live ID.

c) The first time you go to this site, you’ll have to agree to a license agreement.





d) Click “Add New”.




e) Name the Sync Group "LibrarySync". I don’t know the limit of how long this name can be, but I’ve thrown in a lot of text in there and it took it. I wonder if it’s varchar(max). Then click “Next”.

f) Register your server by typing in your server name, user name, and password. Notice how in red it says “Your credentials will be stored in an encrypted format.” This is good news because it saves your credentials when registering other databases on the same server.




g) Then click “Add Hub”. The Hub database is similar to a publishing database in replication. For instance, it will win if there are any update conflicts.

h) Then choose the library2 database and click “Add Member”. Your screen should look something like this:




i) Then click “Next”.

j) You’ll get to a screen that looks like this:




The order you select the tables in this screen is the same order that the tables will be replicated. Remember that we have a foreign key constraint, so it’s real important that we add the authors table before we add the titles table. Click “Finish".

k) OK, now it seems like you’re done, but you’re not. Click on “LibrarySync” and then click “Schedule Sync”. Notice the options you have for scheduling synchronization. You can sync hourly, daily, etc. If you choose hourly, the “Minute” dropdown does not let you schedule at a minute interval, rather it allows you to choose the minute after the hour that the sync will begin. Click “OK”.




l) Technically, your sync is ready to go, but click “Sync Now” and wait a minute or two so we can examine the changes.

Step 5 – Examine the Changes
a) Notice the library2 database has all the schema and data from library1. It also has some other things that SQL Azure Data Sync added for us. BAM! We did it!

b) Look at the 3 tables that SQL Azure Data Sync added in both databases. These tables seem to track sync and schema information.
a. Schema_info
b. Scope_config
c. Scope_info

c) Each user table gets its own tracking table. For instance, we have authors_tracking and titles_tracking. This tells SQL Azure Data Sync which records need to be updated on the other members of the sync group. Notice how this is not an auditing tool like Change Data Capture. It works more like Change Tracking in SQL Server 2008. You won’t get all the changes that led up to the final state of the data.

d) Each user table gets three triggers that are used to keep the databases consistent.

e) There are many stored procedures added to both databases for the same reason. Feel free to poke around and examine the triggers and stored procedures. I found them to be cleanly written. I like how they’re using the MERGE statement, introduced in SQL Server 2008.

f) Feel free to add a record to Library2, and click “Sync Now”. You’ll see it in Library1 in no time, thus proving that the synchronization is indeed bi-directional.

g) On the SQL Azure Data Sync Page, check out the synchronization log by clicking on the Dashboard button.

Final Thoughts
At PDC 2010, Microsoft announced that this service will extend to on-premise SQL Servers. They demo’d how it’s done through an agent that’s installed on the on-premise SQL Server. It should be available to use in CTP 2, which is not publicly available AOTW.

Also, although the initial snapshot pushed the schema down to the library2 database, it will not keep schema in sync without tearing down the sync group and rebuilding it. I recommend you finalize your schema before setting up the sync group.

This is built on the Microsoft Sync Framework. I believe we’ll be seeing this used to synchronize all sorts of data from all sorts of data sources. I think it’s worth learning and I hope this gives you a fair introduction to the technology. Remember to delete at least one of your library databases to keep from being charged. Also, delete your data sync. Good luck!

Wednesday, December 1, 2010

TIG

San Diego Technology Immersion Group (TIG) info



WHERE:
Robert Half Technology
4365 Executive Drive
Suite 450
San Diego, CA 92121

WHEN:
4th Wednesday of every month at 5:45pm, doors lock at 6pm, so don't be late.

WHAT:
We meet once a month to discuss the same book we're all reading.
Those books are chosen off from a range of topics centered on Microsoft Development Technology.
We usually get about 50 members each month.
Right now, we are studying C# and .NET for our beginner track.  We'll do that through January
Starting in February, we will study WPF, XAML, and Silverlight.
Members help each other overcome stumbling blocks while learning new technology.
In addition, we have mentors (experts) helping us understand all this new stuff.



MENTORS:
Ike Ellis
Twitter: http://twitter.com/EllisTeam1
Blog: http://ellisteam.blogspot.com
Website: http://www.ellisteam.net

Scott Reed
Twitter:  http://twitter.com/mscottreed
Blog:  http://brainhzsoftware.com/blog/

Brad Cunningham
Twitter: http://twitter.com/Foovanadil
Blog: http://www.bradcunningham.net/

Jim Bears

OTHER STUFF:
Email Ike to get on the email list so you know about future meetings.  Also, join google groups: http://groups.google.com/group/sdtig

SPECIAL THANKS:
To Robert Half Technologies for donating our meeting space.
To O'Reilly for donating our first book to all of us, Head First C#

Sunday, November 21, 2010

SQL Azure Connection Error with SSIS, SSAS

Today, I was playing around with making a small cube out of the data in the sys.bandwidth_usage table in SQL Azure, and I got an error message which reads:

"Test Connection failed because of an error in initializing provider. Server Name cannot be deteremined. It must appear as the first segment of the server's dns name (servername.database.windows.net.) Some libraries do not send the server name, in which case the server name must be included as part of the user name (username@servername). In addition, if both formats are used, the server names must match."

Test Connection failed because of an error in initializing provider.  Server Name cannot be deteremined.  It must appear as the first segment of the server's dns name (servername.database.windows.net.)

I solved this the way the error says to solve it, by adding what was in the server name field after the user name in the user name field. I also noticed that it can be solved by switching to the native .NET provider, and not using the server name in the user name. I played with the data source in SSIS, too, and it works the same way. Interestingly, SSRS chooses a native .NET SQL provider by default, and therefore doesn't have this problem.

Saturday, November 20, 2010

SQL Azure: AOTW = As Of This Writing

I'm using a new acronym now. Because SQL Azure is changing so much, and I find myself saying and thinking "As Of This Writing, I'm just shortening it to AOTW.

SQL Azure Deprecating sysLogins

There is no sysLogins in SQL Azure. To find out a list of your SQL login accounts use:

select * from sys.sql_logins

The sys.sql_logins dmv doesn't work either. I assume both of these have been taken out because there are no active directory users AOTW.

Thursday, November 18, 2010

Best Agile Tools - By Blog Favorite - Woody Zuill

Here we go again. I asked Woody what his favorite agile tools/blogs are. This was his very well thought out answer (the bolding is my own):

"I don't pay much attention to the Agile blogs - there is a LOT OF NOISE out there with people giving advice about stuff they have insufficient (or no) experience to give advice about, and probably very few people available for taking that advice anyway. Many of the "blogs" are merely lame marketing efforts. The most solid of the bloggers are worth reading - but I don't typically follow them, but I'm more likely to click a link to an article if it is from a blogger who is someone I respect.

Tools for managing an Agile effort are another matter.

My one general rule about Agile Tools is DON'T (if the tool is in the form of a computer application). There are better alternatives. (I am not talking about refactoring tools, testing tools, etc. here - but the management tools, the communication tools, things like that).

Agile is best done manually, and the computerized management tools will in most cases be counter-productive IMHO. (Or IMNSHO - which is In My Not So Humble Opinion).

In a nutshell: You learn Agile by study and practice and doing and talking about the doing and so on. Tools often block learning by forcing you to follow what someone else decided is useful. Tools needlessly complicate the simplicity of Agile. Simplify, simplify.

Like the Agile Manifesto says: We value Individuals and Interactions over Processes and Tools.

I take that to at least partly mean that we get a lot more value out of focusing on empowering Individuals and improving our ability to interact well as individuals than on following some Process or using some Tool.

I have only one rock solid, immutable rule, however (that I reserve the right to change anytime): Continuously Inspect and Adapt - continuous improvement of our thinking, our understanding, how we learn, how we get along, our principles, our practices, our processes, our tools, etc.

So, if I found a tool that looks like it would bring me value, I would certainly investigate it, try it, and use it if it proves to be userful. And I would continually evaluate its usefulness. But typically - I follow the rule of DON'T when it comes to computerized Agile management tools.

Right now, my favorite tools continue to be physical ones - white boards and erasable markers, sticky notes (small) and sticky notes (huge), 3 x 5 index cards and Sharpies, face-to-face interactions and information radiators, blank flip charts and a digital camera, eye of newt and toe of frog (to paraphrase Shakespeare)."

Wednesday, November 17, 2010

TechEd Berlin 2010 - Link to Videos on SQL Azure and SQL Server

I didn't get a chance to go to TechEd Berlin, but I've been watching the videos online. The user interface to the website is not super great. I shouldn't complain too much. I'm super grateful that they posted all the videos from that week online so quickly. By comparison, it will take two weeks to get the SQL Pass 2010 videos online.

Here's where the SQL Azure videos start (page 19 of the video list):
http://www.msteched.com/2010/Europe/Page19/

SQL Azure Reporting videos are on page 20:
http://www.msteched.com/2010/Europe/Page20/

Here is where the SQL videos start (page 18):
http://www.msteched.com/2010/Europe/Page18/

SQL Videos for BI/PowerPivot etc (page 21):
http://www.msteched.com/2010/Europe/Page21/

There were a few other presentations that I thought would be interesting to the SQL developer/DBA:
Introduction to PowerShell
http://www.msteched.com/2010/Europe/WSV301

SSRS 2008R2 Integration with SharePoint 2010
http://www.msteched.com/2010/Europe/OFS330

Creating Self-Service Analytic BI Applications with SharePoint 2010
http://www.msteched.com/2010/Europe/OFS206

Code First Development with Entity Framework
http://www.msteched.com/2010/Europe/DEV212

Building Business Applications with Visual Studio LightSwitch (which seems to be the MS Access front end for SQL Server....it's super cool.)
http://www.msteched.com/2010/Europe/DEV206

The Future of C#
http://www.msteched.com/2010/Europe/DEV301

Phew, that ought to keep us busy for a long time. Have fun and happy watching!

Thursday, November 4, 2010

Finding The Difference Between Two Dates that are in Seperate Rows in T-SQL

This problem is often solved with a cursor, but is easily re-written using a CTE. In the below sample, we are using data from a university who's trying to figure out the time between when a course ended and when the next course began. So the data looks something like this:
learnerID StartDate CompletedDate
0000131801 2010-07-01 00:00:00.000 2010-09-23 00:00:00.000
0000131801 2010-10-01 00:00:00.000 2010-12-24 00:00:00.000
0000212970 2009-11-01 00:00:00.000 2010-01-24 00:00:00.000
0000212970 2010-02-01 00:00:00.000 2010-04-26 00:00:00.000
0000212970 2010-03-01 00:00:00.000 2010-05-24 00:00:00.000
0000212970 2010-06-01 00:00:00.000 2010-08-24 00:00:00.000
0000212970 2010-07-01 00:00:00.000 2010-09-23 00:00:00.000
0000212970 2010-10-01 00:00:00.000 2010-12-24 00:00:00.000

and the query that will give them the average days between a course ending and the next course starting looks like this:

with lc
as
(
select row_number() over (order by learner_id, start_date, learner_course_id) as rownum
, learner_course_id
, learner_id
, start_date
, coalesce(completed_date, end_date) as CompletedDate
from learner_courses
)
select datediff(d, lc1.completeddate, lc2.start_date) as daysbetweenstarts, *
from lc lc1
join lc lc2
on lc1.learner_id = lc2.learner_id
and lc2.rownum = (lc1.rownum + 1)
where datediff(d, lc1.completeddate, lc2.start_date) > -1

Wednesday, November 3, 2010

Best Books on TDD, Agile, and SCRUM by Woody Zuill

My friend, Woody Zuill, is a developer and manager that I respect an awful lot. Recently he was asked to recommend great books on agile software development. Since Woody is always reading, he seemed like a great guy to ask. His response was thoughtful and interesting, so I thought I'd post it below:

"The books I've found useful all have holes in them. You have to get a fair amount of bad to get a small amount of good.

- For me, the Lean books by the Poppendiecks were probably the most good with the least bad.

- Kent Beck's XP book - both editions. I think you need both to get it all. These books have been very useful to me. A lot more real stuff and real thinking than most of the "How To Agile" books.

- Kent Beck's TDD book

- The second edition of Alistair Cockburn's book - Agile Software Development: The Cooperative Game. I think the first edition missed the boat in a lot of things. I think he must have learned a lot by the time the second edition came out. I don't know how experienced he actually is, but I like the nature of his book. Note: His book on How to Survive an OOP project was one of the worst books I have seen.

- Of course, Michael Feather's Legacy Code book is great. I recommend that for all developers.

- And Bob Martin's Clean Code and Agile Software Development books are must reads. The Bob Martin Agile book is overall probably the most useful book I've read (on software development) - but it is a hard read in some ways, and very difficult to sort through.

- I found Diana Larsen and Esther Derby's Agile Retrospectives book very useful to adjust my thinking about making teams work well.

I used to like Mike Cohn's books on estimating and so on - but only barely. Not so much anymore. Same with Ken Schwaber's Scrum books, in some ways I wish they were never written.

I'ver read about 20 or 30 books on the topic, and flipped through a lot of others. Most are misleading at best. Knowing what I know about things in general, I suspect a lot of this garbage is written by people who don't really know what they are talking about and aren't able to admit it to themselves. I want to believe that - otherwise the authors are being purposely misleading or deceptive and I am not ready to accept that.

There is one book that I really loved, and felt the guy was actually right on - but I searched all over the Internet tonight looking for it and couldn't find it. When I get home I'll look around and see if I can find it. [ I found it: "Sustainable Software Development: An Agile Perspective" by Kevin Tate. I must have "loaned" it to someone because I couldn't find it anywhere at home. I remember it as being very good and humble - but I read it about 5 years ago and haven't seen it since so a re-read is in order, and I reserve the right to change my mind about its usefulness. ]

Well... there have been a lot of good in a lot of those (and other) books. And for me, the main use was to help me think through things. There is a lot of garbage to sift through, though."


Great stuff, huh? Below are links to all the books he references in the email:

Kent Beck's Books

Agile Software Development: The Cooperative Game

Working Effectively with Legacy Code

Bob Martin's Books

Clean Code

Esther Derby's Agile Retrospectives

Mike Cohn's Books

And the gem:

Sustainable Software Development

Tuesday, November 2, 2010

T-SQL - Split Long String into Several Small Strings

This is a fantastic little function:

CREATE FUNCTION dbo.Split (@sep char(1), @s varchar(8000))
RETURNS table
AS
RETURN (
WITH Pieces(pn, start, stop) AS (
SELECT 1, 1, CHARINDEX(@sep, @s)
UNION ALL
SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1)
FROM Pieces
WHERE stop > 0
)
SELECT pn,
SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 8000 END) AS s
FROM Pieces
)

I found it here:

Stack Overflow

and here:

SQLTeam

Monday, November 1, 2010

TimeMatters Master Audit File Error



If you are running TimeMatters in a replicated environment and you get the error:

Unable to access Master Audit File
Record Audit will not be saved.

ERROR: The insert failed. It conflicted with an identity range check constraint in database 'TimeMatters10', replicated table 'lntmuser.Audit.Current', column 'Ident'. If the identity column is automatically managed by replication, update the range as follows: f


The run the following command on the publisher and it should fix it:

exec sp_adjustpublisheridentityrange @table_name = 'audit current', @table_owner = 'lntmuser'

Monday, October 25, 2010

LA Code Camp Files


Hi There!

Thanks for coming to my LA Code Camp session on SQL Server Performance Optimization. I hope you had a great time, learned a lot, and left with action items that can immediately help you at work.

Here's a link to the download files:

LA Code Camp.zip

See you soon!

Ike

ID Columns With No Indexes

This is a really simple script that will tell you what columns with "ID" in the name don't have indexes. Often, foreign key constraints are not added to the database. I'm sure the referrential integrity is being enforced in the business logic of the application. At least I hope so. In any case, the optimizer still needs those columns to be indexed.




select * from sys.columns c
where c.name like '%id%'
and c.object_id not in
(
select object_id from sys.index_columns
)


Then I created this script to just go ahead and create a basic nonclustered index on those columns. Just copy & paste the results into a SQL Server Management Studio query window and run it.



select 'create nonclustered index IX_' + t.name + '_' + c.name + '_001'
+ ' ON ' + schema_name(t.schema_id) + '.' + t.name + '(' + c.Name + ');'
from sys.columns c
join sys.tables t
on c.object_id = t.object_id
where c.name like '%id%'
and c.object_id not in
(
select object_id from sys.index_columns
)



You'll want to include other columns in these indexes to make sure your indexes are covering the queries, but this should get you started. Make sure the results are return in text, not grid.

Saturday, October 16, 2010

T-SQL Random Date


I wrote this code to generate a random date between two dates. I wanted a random date for each row in a table. Use @beginDate and @endDate to specify the lower and upper bounds of the random date. The only tricky part is the checksum(newid()). You can try using the rand function without it, but you'll just get the same random date for every row in the table.

declare @beginDate datetime, @endDate datetime
set @beginDate = '1/1/2000'
set @endDate = getdate()

select dateadd(d, cast(-1 * datediff(d, @beginDate, @endDate)
* rand(checksum(newid())) as int), @endDate)
from sys.objects


If you want to update a date column with a random date, you can just do this:

update Orders
set orderdate = dateadd(d, cast(-1 * datediff(d, @beginDate, @endDate)
* rand(checksum(newid())) as int), @endDate)

Wednesday, September 29, 2010

Blind Spot - T-SQL $Identity

I've been working with SQL Server for 12 years, but this short cut escaped me.

In Transact-SQL, the $IDENTITY keyword allows us to refer to the identity column without knowing its name. Since identity columns are often primary keys, we could use this as a short cut for always referring to the PK. This would be awesome to use in a code generator or an ORM.

This is not to be confused with @@IDENTITY or SCOPE_IDENTITY(), which tells us the actual number auto generated by the IDENTITY column (though each behaves in different ways.)

Test it out with this script:

use tempdb
go

create table test
(
id int identity(1,1)
, descr varchar(100)
)
go

insert into test
(descr)
values
('first record')
, ('second record')
, ('third record')
go

select $identity, descr from test

Thursday, September 23, 2010

TIG Notes

Yesterday at TIG I mentioned that the Visual Studio tips from Sara Ford had helped me to be a faster developer and worker. Many of you asked where you could find her blog, so here it is:

Sara Ford's BLOG

San Diego TIG - 2nd Meeting


The Tech Immersion Group met last night, and we had a great time. Next month, we'll be reading Head First C#, Chapters 6 - 8, and Lab 2. We'll be meeting on October 27th.

We also setup a new Google Group. DM me for an invitation.

Monday, September 13, 2010

San Diego Tech Immersion Group



TIG - Tech Immersion Group

WHAT

The Tech Immersion Group is founded on the belief that learning new technology can be fun. Our first topic will be C# and .NET. Future topics include Silverlight, SharePoint, WCF, Entity Framework, LINQ, and Azure. The idea is as follows:

1) We will meet monthly to discuss about 200 – 300 pages of a book we’ve chosen.

2) We will stay with the same topic for several months (probably until we’re finished with the book.)

3) We will study for certification exams together.

4) We will write sample code and software projects.

5) This will be a safe place where any question can be asked (Ugh, I hope you get a good answer).



WHO

All are welcome to join the group. We do need to know who they are ahead of time so we can ensure a book is provided. We’ve been able to get our first book donated by O’Reilly Press. Hopefully, we can keep this sweet deal going.

I’m Ike Ellis, and I’ve been writing software for 12 years. Software I have written is currently in use by several thousand people. I love to teach and I love to learn. I can’t wait to meet you and get started on this together!

THE COMMITMENT

You will get a free book, free time from a mentor, and really valuable knowledge. In return, we ask:

1) That you show up on time and ready to learn.

2) That you commit to being there every month.

3) That you consider becoming a member of the San Diego .NET User Group ($50 annually.)

4) That you write a review on Amazon regarding the book you got for free (This will keep the free books coming.)

That’s it! Let’s get ready to learn a ton!

WHERE

Robert Half Technology
4365 Executive Drive
Suite 450
San Diego, CA 92121

WHEN

The 4th Wednesday of every month. Please be there at 5:45pm, as the doors to our building will lock by 6pm. Don’t be late!

Ike Ellis Contact Info
Twitter: @EllisTeam1
FaceBook: http://www.facebook.com/ellisike
Linked In
http://ellisteam.blogspot.com
http://www.ellisteam.net



A BIG THANK YOU TO O'RIELLY FOR DONATING OUR BOOKS!!!
Visit them at http://www.oreilly.com.

Wednesday, September 8, 2010

T-SQL Session, Promised Script

Several people asked that I post this script on T-SQL fundementals:

USE Northwind

SELECT *
FROM Customers;

SELECT CompanyName
, ContactName
, ContactTitle
--, Address
--, City
--, Region
--, PostalCode
FROM Customers;


SELECT CompanyName
, ContactName
, ContactTitle
, Address
, City
, Region
, PostalCode
FROM Customers
ORDER BY ContactName;




SELECT CompanyName
, ContactName
, ContactTitle
, Address
, City
, Region
, PostalCode
FROM Customers
ORDER BY CompanyName, ContactName DESC; --ASC is the default.

SELECT CompanyName
, ContactName
, ContactTitle
, Address
, City
, Region
, PostalCode
FROM Customers
WHERE CompanyName = 'Alfreds Futterkiste'
ORDER BY ContactName DESC; --ASC is the default.

--Comparison Operators
--=
--<>
--!=
--<
--<=
--!<
-->
-->=
--!>
--BETWEEN
--IS NULL

SELECT CustomerID
, OrderID
, Freight
, ShippedDate
FROM Orders
WHERE Freight > 100;

SELECT CustomerID
, OrderID
, Freight
, ShippedDate
FROM Orders
WHERE Freight !> '100';

SELECT CustomerID
, OrderID
, Freight
, ShippedDate
FROM Orders
WHERE Freight <= '100' ;

SELECT CustomerID
, Region
FROM Customers
WHERE Region <> NULL;

SELECT CustomerID
, Region
FROM Customers
WHERE Region <> 'CA';

SELECT CustomerID
, Region
FROM Customers
WHERE Region <> 'CA' OR Region IS NOT NULL;

SELECT CustomerID
, OrderID
, Freight
, ShippedDate
FROM Orders
WHERE Freight BETWEEN '10.14' AND '43.90'
ORDER BY Freight ;

--Logical Operators
--AND
--OR
--NOT

SELECT CustomerID
, OrderID
, Freight
, ShippedDate
FROM Orders
WHERE Freight BETWEEN '10.14' AND '43.90'
OR ShippedDate BETWEEN '1/1/1997' AND '12/1/1997'
ORDER BY ShippedDate, Freight ;

SELECT CustomerID
, OrderID
, Freight
, ShippedDate
FROM Orders
WHERE Freight BETWEEN '10.14' AND '43.90'
OR ShippedDate BETWEEN '1/1/1997' AND '12/1/1997'
ORDER BY ShippedDate, Freight ;


--I want all orders from CustomerID = VINET with a freight over $10 and all orders from CustomerID TOMSP with a freight over $10.
SELECT CustomerID
, OrderID
, Freight
FROM Orders
WHERE Freight > '10'
AND CustomerID = 'VINET'
OR CustomerID = 'TOMSP'
ORDER BY CustomerID;

--SQL is reading this from left to right. So technically we can do this:
SELECT CustomerID
, OrderID
, Freight
FROM Orders
WHERE CustomerID = 'VINET'
AND Freight > '10'
OR CustomerID = 'TOMSP'
AND Freight > '10'
ORDER BY CustomerID;

SELECT CustomerID
, OrderID
, Freight
FROM Orders
WHERE (CustomerID = 'VINET'
OR CustomerID = 'TOMSP')
AND Freight > '10'
ORDER BY CustomerID;

--IN Operator
SELECT CustomerID
, OrderID
FROM Orders
WHERE (CustomerID = 'VINET'
OR CustomerID = 'TOMSP'
OR CustomerID = 'HANAR'
OR CustomerID = 'SUPRD');


SELECT CustomerID
, OrderID
FROM Orders
WHERE CustomerID IN ('VINET', 'TOMSP', 'HANAR', 'SUPRD');

SELECT CustomerID
, OrderID
FROM Orders
WHERE CustomerID NOT IN ('VINET', 'TOMSP', 'HANAR', 'SUPRD');


--WILDCARDS
SELECT CompanyName
FROM Customers
WHERE CompanyName LIKE 'A%';


SELECT CompanyName
FROM Customers
WHERE CompanyName LIKE '%A';


SELECT CompanyName
FROM Customers
WHERE CompanyName LIKE '%A%';


SELECT CompanyName
FROM Customers
WHERE CompanyName LIKE 'W%A';


SELECT CompanyName
FROM Customers
WHERE CompanyName LIKE 'F%A%';

SELECT CompanyName
FROM Customers
WHERE CompanyName LIKE '[FM]%';


SELECT CompanyName + ' - ' + ContactName
+ ' - ' + ContactTitle AS HeaderLine1
FROM Customers
WHERE CompanyName + ' - ' + ContactName
+ ' - ' + ContactTitle LIKE 'A%'
ORDER BY HeaderLine1;

--Order of Operation
--1.FROM clause
--2.WHERE clause
--3.GROUP BY clause
--4.HAVING clause
--5.SELECT clause
--6.ORDER BY clause

--Calculated fields - Math
SELECT
OrderID
, ProductID
, UnitPrice
, Quantity
, UnitPrice * Quantity AS TotalPrice
FROM [Order Details];

--Math operators
-- +, -, *, /


--FUN WITH FUNCTIONS!

--Figuring out envelope size for a mailing
SELECT CompanyName
, LEN(CompanyName) AS NumberOfChars
FROM Customers;

--Uppercase CompanyName
SELECT UPPER(CompanyName) AS UpperCompany
FROM Customers;

--STRING FUNCTIONS
--LTRIM, RTRIM
--SUBSTRING
--RIGHT
--LEFT
--SOUNDEX

SELECT ContactName
FROM Customers
WHERE SOUNDEX(ContactName) = SOUNDEX('paul');

--Date Functions
--DATEDIFF
--DATEADD
--MONTH
--YEAR
--DATEPART

--The difference between order date and ship date in days - T-SQL help is great with Functions - SHIFT-F1
SELECT
OrderDate
, ShippedDate
, DATEDIFF(d, OrderDate, ShippedDate) AS DaysToShip
FROM Orders;

--The orders that took longer than 15 days to ship
SELECT
OrderDate
, ShippedDate
, DATEDIFF(d, OrderDate, ShippedDate) AS DaysToShip
FROM Orders
WHERE DATEDIFF(d, OrderDate, ShippedDate) > 15;


--Aggregates
--MAX
--MIN
--SUM
--AVG
--COUNT
--COUNT DISTINCT

--Most recent Order Date
SELECT MAX(OrderDate) AS MaxOrderDate
FROM Orders;

--First Order Date
SELECT MIN(OrderDate) AS MaxOrderDate
FROM Orders;

--Let's combine this into a subquery
SELECT OrderID
FROM Orders
WHERE OrderDate =
(
SELECT MAX(OrderDate) AS MaxOrderDate
FROM Orders
);

--Max Days to Ship --Null values out of aggregation
SELECT MAX(DATEDIFF(d, OrderDate, ShippedDate)) AS MaxDaysToShip
FROM Orders;

--Average Days to Ship
SELECT AVG(DATEDIFF(d, OrderDate, ShippedDate)) AS MaxDaysToShip
FROM Orders;

--Orders above my average days to ship
SELECT OrderID
, CustomerID
, OrderDate
, ShippedDate
, DATEDIFF(d, OrderDate, ShippedDate) AS DaysToShip
FROM Orders
WHERE DATEDIFF(d, OrderDate, ShippedDate) >
(
SELECT AVG(DATEDIFF(d, OrderDate, ShippedDate)) AS MaxDaysToShip
FROM Orders
) ;


SELECT CustomerID
, AVG(DATEDIFF(d, OrderDate, ShippedDate)) AS MaxDaysToShip
FROM Orders
GROUP BY CustomerID;

--Customers with an average greater than the average
SELECT CustomerID
, AVG(DATEDIFF(d, OrderDate, ShippedDate)) AS MaxDaysToShip
FROM Orders
GROUP BY CustomerID
HAVING AVG(DATEDIFF(d, OrderDate, ShippedDate)) >= 15;

--JOINS
--INNER
--RIGHT OUTER
--LEFT OUTER

--Inner Join
SELECT c.CompanyName
, c.CustomerID
, o.OrderDate
, o.ShippedDate
FROM Customers c
JOIN Orders o
ON c.CustomerID = o.CustomerID
ORDER BY c.CompanyName

--LEFT OUTER JOIN
SELECT c.CompanyName
, c.CustomerID
, o.OrderDate
, o.ShippedDate
FROM Customers c
LEFT OUTER JOIN Orders o
ON c.CustomerID = o.CustomerID
WHERE o.CustomerID IS NULL
ORDER BY c.CompanyName


SELECT *
FROM Customers

--CRUD
INSERT INTO Customers
(CustomerID, CompanyName)
VALUES
('ELLIS', 'EllisTeam')

DELETE FROM Customers
WHERE CustomerID = 'ELLIS'

UPDATE Customers
SET ContactName = 'Ike Ellis'

SELECT * FROM Customers
WHERE CustomerID = 'Ellis'

DELETE FROM Customers
WHERE CustomerID = 'ELLIS'


UPDATE o
SET Freight = Freight + 1
FROM Customers AS c
JOIN Orders AS o
ON c.CustomerID = o.CustomerID
WHERE Region = 'CA'


--Tips
--================
--Sometimes T-SQL doesn't read as intuitively as we like. Use white space and comments.

--Limit record results to as little as possible. (Good for network, disk, memory, users, and performance.)

--Nulls

--Connection Tips - Coloring and highlighting

--Always use Linenumbers

--Copy and paste results into EXCEL for adhoc stuff

--Show an error message (RAISEERROR) with severity
RAISERROR (N'This is message.', 18, 1);

--Learn about Query Plans
SELECT *
FROM Customers c
JOIN Orders o
ON c.CustomerID = o.CustomerID
JOIN [Order Details] od
ON o.OrderID = od.OrderID
JOIN Products p
ON od.ProductID = p.ProductID
ORDER BY c.CompanyName

--Object Explorer Drag & Drop

--Avoid Cursors

--Be careful updating and deleting (WHERE clauses, backup, SELECT using the WHERE clause, then Delete with the same one.)

--Never change production without changing dev and beta first

--Don't bother coding for portability or language independence.

--Consider using synonyms for long table names
CREATE SYNONYM Cust FOR dbo.Customers
SELECT * FROM Cust
DROP SYNONYM Cust

--TRUNCATE VS DELETE
--Logged and WHERE
DELETE FROM Temp1

--Non-logged and no WHERE, but fast
TRUNCATE TABLE Temp1


--Common question - How to delete duplicates
CREATE TABLE dbo.duplicateTest
(
[ID] [int] ,
[FirstName] [varchar](25),
[LastName] [varchar](25)
) ON [PRIMARY]

INSERT INTO dbo.duplicateTest VALUES(1, 'Bob','Smith')
INSERT INTO dbo.duplicateTest VALUES(2, 'Dave','Jones')
INSERT INTO dbo.duplicateTest VALUES(3, 'Karen','White')
INSERT INTO dbo.duplicateTest VALUES(1, 'Bob','Smith')

SELECT *
FROM dbo.duplicateTest

SELECT *
FROM dbo.duplicateTest
WHERE ID = 1 AND FirstName = 'Bob' AND LastName = 'Smith'

DELETE TOP(1) FROM dbo.duplicateTest WHERE ID = 1

DROP TABLE duplicateTest

UPDATE Customers
SET ContactName = 'Ike Ellis'


WHERE CustomerID = 'ELLIS'


DELETE FROM Customers
WHERE CustomerID = 'ELLIS'

Microsoft Lightswitch = Enterprise Microsoft Access

Lynn Langit blogged on Microsoft Lightswitch and that made me go check it out. It's a beta tool for Visual Studio that allows screens and database tables to be created with minimal software development or training.

This reminds me of Microsoft Access in the 1990s. Access made it so easy to create a database, data entry screens, and reports, that tons of lay people were writing custom apps for their own purposes. Because Access would collapse after it had 12 concurrent users, professional developers would need to be hired to port the app to SQL Server.

Lightswitch finally provides all of those great Access features for SQL Server, SQL Azure, and cloud development. I'll post more about it after I've played with it awhile.

Here are some links:

Lynn's Original Post

MSDN Lightswitch Site

Lightswich: 15 Reasons Non-Programmers Should Try It Out

UPDATE: Carl Franklin on .NET Rocks released a podcast on LightSwitch last month.
.NET Rocks Podcast on LightSwitch

Thursday, August 26, 2010

TIG - Head First C# - 1st Assignment




Our first reading assignment:

-Read the part under your commitment, and decide if you can do those things.
-Make and O’Reilly account.
-Forward that account logon name to me.
-Read Chapters 1 – 5 of our book.
-See you on September 22nd!
-Optionally, show me a mortgage calculator.

Thursday, July 15, 2010

T-SQL: Use A Variable to Create a ColumnList for a PIVOT Query of Dates

DECLARE @BeginDate datetime
DECLARE @EndDate datetime

SET @BeginDate = '7/1/2010';
SET @EndDate = '7/31/2010';

--Create a dates table with every date between 7/1/2010 and 7/31/2010
WITH mycte AS
(
SELECT cast(@BeginDate as datetime) DateValue
UNION ALL
SELECT DateValue + 1
FROM mycte
WHERE DateValue + 1 < @EndDate

)
SELECT CONVERT(varchar,DateValue,101) as StDate INTO #dates from mycte
OPTION (MAXRECURSION 0);

--Get each date in the #dates table as a set
select ',[' + StDate + ']' from #dates;

--Get it as a long string. We use the XML path for that, which is awesome.
select ',[' + StDate + ']' from #dates for XML path('');

--Use the STUFF function to remove the leading comma. This is a pretty cool way to do that, rather than messing around with LEN and stuff.
SELECT STUFF((select ',[' + StDate + ']' from #dates for XML path('')),1,1,'') AS NoLeadingCommaOneLongString;

--Use the same query to set a variable value.
DECLARE @ColumnList varchar(max);
SET @ColumnList = STUFF((select ',[' + StDate + ']' from #dates for XML path('')),1,1,'');

--Here's a sample table with dates and names.
CREATE TABLE #SampleWorkDates
(
Workeddate datetime
, [name] varchar(100)
, workdone int
);
INSERT INTO #SampleWorkDates
SELECT '7/12/2010','john', 100 UNION
SELECT '7/12/2010','john', 110 UNION
SELECT '7/12/2010','debby', 102 UNION
SELECT '7/18/2010','john', 60 UNION
SELECT '8/10/2010','alex', 89 UNION
SELECT '9/11/2010','john', 120;

--We need to pivot that data, but the column list is really long.

--Rather than writing out all the columns by hand, like this:
select * from
(select [Name],count([Name]) over (partition by [Name]) as Total,CONVERT(varchar,[WorkedDate],101) as Workeddate,COUNT(*) as cnt from #SampleWorkDates
where CAST(WorkedDate AS datetime) >= '07/01/2010' and CAST(WorkedDate AS datetime) <= '07/31/2010' group by [Name],CONVERT(varchar,[WorkedDate],101))p
pivot (MAX([name]) for WorkedDate in ([07/01/2010],[07/02/2010],[07/03/2010],[07/04/2010],[07/05/2010],[07/06/2010],[07/07/2010],[07/08/2010],[07/09/2010],[07/10/2010],[07/11/2010],[07/12/2010],[07/13/2010],[07/14/2010],[07/15/2010],[07/16/2010],[07/17/2010],[07/18/2010],[07/19/2010],[07/20/2010],[07/21/2010],[07/22/2010],[07/23/2010],[07/24/2010],[07/25/2010],[07/26/2010],[07/27/2010],[07/28/2010],[07/29/2010],[07/30/2010]))pvt


--We can just use the @ColumnList variable we used before. It looks cleaner and is reusable.
declare @sql nvarchar(max);
set @sql = 'select * from (select [Name],count([Name]) over (partition by [Name]) as Total,CONVERT(varchar,[WorkedDate],101) as Workeddate,COUNT(*) as cnt from #SampleWorkDates
where CAST(WorkedDate AS datetime) >= ''' + CONVERT(varchar, @BeginDate, 101) + ''' and CAST(WorkedDate AS datetime) <= ''' + CONVERT(varchar, @EndDate, 101) +
''' group by [Name],CONVERT(varchar,[WorkedDate],101))p
pivot (sum(cnt) for WorkedDate in (' + @ColumnList + '))pvt';

PRINT @sql;

exec(@sql);


DROP TABLE #SampleWorkDates;
DROP TABLE #dates;

T-SQL: Script to Populate a Dates Table With Recursion and a CTE

I used to create dates tables like this:

--********************************
DECLARE @BeginDate datetime
DECLARE @EndDate datetime

SET @BeginDate = '1/1/1900'
SET @EndDate = '12/31/2050'

CREATE TABLE #Dates ([date] datetime)

WHILE @BeginDate <= @EndDate
BEGIN
INSERT #Dates
VALUES
(@BeginDate)

SET @BeginDate = @BeginDate + 1
END
SELECT * FROM #Dates
DROP TABLE #Dates
--********************************

That works fine, but it has a lot to clean up, executes slowly, and has a lot of code. Plus it uses looping.

This is a better way:
--********************************
WITH mycte AS
(
SELECT cast('1900-01-01' as datetime) DateValue
UNION ALL
SELECT DateValue + 1
FROM mycte
WHERE DateValue + 1 < '2050-12-31'

)
SELECT DateValue
FROM mycte
OPTION (MAXRECURSION 0)
--********************************

By default, the MAXRECURSION option is set to 100. I set it to zero, which means we could go into an infinite loop. I use the WHERE clause to make sure the loop bails out at 12/31/2050. Without the WHERE clause, we'd be hosed.

Thursday, July 1, 2010

SSRS 2008 - Adding SSL After Installation

If you can't get it to work, try doing everything in this thread:

http://prologika.com/CS/forums/t/946.aspx

And everything here:

http://technet.microsoft.com/en-us/library/ms345223(SQL.100).aspx


Also, SSRS 2008 does not support wildcard certificates, ie *.yourdomain.com. Obtain a special dedicated SSL cert YourServerName.yourdomain.com, then apply it on the SSRS 2008 server. This is what worked for us at a client, after calling PSS. This is a known issue at Microsoft and they are working on a better solution.

Wednesday, May 19, 2010

Cool Control Panel View

This went around a few months ago, but in case you missed it, create a folder on your desktop and rename it to this: GodMode.{ED7BA470-8E54-465E-825C-99712043E01C}

This will create a new control panel icon on your desktop with a ton of cool options.

Looks like this:

Friday, April 23, 2010

Data Explosion - Great Story


I got this story from Scott Cameron of Hitachi Consulting, although I've heard it before:

The story of the man who invented chess can help illustrate the problem of data explosion.

The man lived in India, and according to legend his name was Sessa. The king of India was very impressed with the game of chess and asked Sessa to name his reward. Sessa's request was so modest that it offended the king: He asked simply for one grain of rice for the first square of his chess board, two grains for the second square, four grains for the third, and so forth, doubling the number of grains of rice for each of the 64 squares of the board. Of course, by the time the king's magicians calculated the total amount of rice needed to pay the reward, they realized that it would require a warehouse 3 meters by 5 meters by twice the distance to the sun to pay the reward.

The king gave Sessa a sack, pointed him to the warehouse and told him to go count out his reward - no rush.

When numbers increase geometrically (like they do in a data warehouse), they get large very quickly.

Monday, April 12, 2010

Business Intelligence Quote

"You can spend millions building the data warehouse, but if you don't have the back office under control, you are wasting your money."
Mike Costa
Corporate Director of Quality Process & Architecture
The Dow Chemical Company

Saturday, April 10, 2010

Feedback Loops - Donella Meadows



"Examples of compelling feedback is not hard to find. Suppose taxpayers got to specify on their return forms what government services their tax payments must be spent on....Suppose any town or company that puts a water intake pipe in a river had to put it immediately downstream from its own wastewater outflow pipe. Suppose any public or private official who made the decision to invest in a nuclear power plant got the waste from that facility stored on his or her lawn...Suppose the politicians who declare war were required to spend that war in the front lines.

There is a systematic tendency on the part of human beings to avoid accountability for their own decisions. That's why there are so many missing feedback loops."

She goes on to relate a story about Amsterdam:



"Near Amsterdam, there is a suburb of single-family houses all built at the same time, all alike. For some unknown reasons it happened that some of the houses were built with the electric meter down in the basement. In other houses, the electric meter was installed in the front hall.

It was discovered that the houses with the electric meter in the hall used 1/3 less energy."

She explains that this is because the feedback loop was available for all to see.

This is the main purpose of business intelligence. To provide a feedback loop that provides accountability at all levels of an organization.

Friday, April 9, 2010

Donella H. Meadows Quote

"Purposes are deduced from behavior, not from rhetoric or stated goals."
Donella H. Meadows
Thinking in Systems

"An important function of almost every system is to ensure its own perpetuation."
Same as above

Donella is not speaking of software systems, but rather behavior systems. She's speaking about the war on drugs, welfare, health care, national security, the environment, or any other societal or natural system.

"Keeping sub-purposes and overall system purposes in harmony is an essential function of successful systems."
Same as above

"We misperceive risk, assuming that some things are much more dangerous than they really are and others much less. We live in an exaggerated present - we pay too much attention to recent experience and too little attention to the past, focusing on current events rather than long-term behavior"
Donella H. Meadows
Thinking in Systems

"Usually the greater the discrepancy between the goal and the actual situation, the more emphatic the action will be."
Same as above

"The most damaging example of the systems archetype called "drift to low performance" is the process by which modern industrial culture has eroded the goal of morality. The workings of the trap have been classic, and awful to behold."
Same as above

"We know what to do about drift to low performance. Don't weigh the bad news more heavily than the good. And keep standards absolute."
Same as above

Microsoft OneNote, an Answer to Prayer



Since my business is growing, I find that I'm forgetting more and more things. If it doesn't fit neatly in a todo or a calendar event, I have trouble keeping track of it.

I've been asking people all over what they did to keep track of non-actionable data. Most of them had no answers for me. Beau Merseraeu said that he's using OneNote. I'm well-acquainted with the other Office products, but OneNote always seemed like tablet software to me. I was wrong.

If you read a quote that you want to remember, throw it in OneNote. If you see statistics to help you with a sales presentation....OneNote. I'm using it more and more. It's like having an online journal, but it is organizable, which allows for fast data retrieval. I love it and wish I hadn't wasted so much time not using it.

Monday, April 5, 2010

DigiGirlz - Blowing Away the Girl/Programmer Myths


I spent last Friday volunteering with DigiGirlz. This awesome event, sponsored by Microsoft, exposes High School age girls to technology. In one day, they learn programming, database querying, robotics, and video game programming. In between classes, they meet IT professionals who explain what life is like when you choose a career in technology. All of the girls had a great time and learned a lot.

Here are some myths that DigiGirlz helps debunk:

Myth #1: Girls don't like programming, math, or science.

False. While teaching some of these classes, I never saw a student waver in her interest. I never caught one texting on her cell phone. I never saw one not complete an assignment. When the programming class was over, many of them were disappointed that it ended. Many asked how they could program at home on their own time. Most of them thirsted for more.

Myth #2: Girls aren't good at programming.

Totally false. During a one hour SmallBasic class, I saw many students immediately understand the language constructs. Some girls only needed about 10 minutes of direction and they were free styling. By the end of the class, the girls were shocking me with the images and vectors they were programmatically drawing. They fluently understood the math, and could quickly grasp the creation of geometric shapes. I've seen adult programmers who struggled with concepts that the girls immediately learned.

Myth #3: Girls who do like technology and programming are basically boys (or aren't very cute.)

Lynn Langitt (SoCalDevGal) and Linda Routson (Microsoft Account Manager Extraordinaire) did a great job finding female instructors for these courses. They were all beautiful women who were professional, intelligent, and feminine. One was a programmer for a fashion company. These examples taught the girls that you can be good at traditional male professions without surrendering what you like about being a girl.

I think any girl would enjoy this event. Find more information here:

DigiGirlz

Tuesday, March 30, 2010

ASP.NET AJAX Still Flickering and Posting Back

We looked everywhere to solve this problem, and finally found this blog post. Neil clearly outlines the solution to our issue and it worked for us.

neil kilbride's blog

Thursday, March 18, 2010

Mind Map Software - Free Mind


A friend of mine, Chris York, turned me on to mind mapping as a way to flush out projects and requirements. I love it.

Mind mapping is a way to document and diagram meeting notes, while the meeting is taking place. It allows the meeting to be a freeform expression of thoughts, while maintaining the general topic.

During meetings, conversations tend to move from one topic to another, seemingly directionless. This is an excellent place to capture salient points about a software or technology project, without overcontrolling the meeting. It can also help to avoid repetition, because you can go to a branch on the map and add or remove detail as needed.

You can also use mindmapping outside meetings to organize your own thoughts and projects. It will help you take a general idea and create concrete action items and ToDos.

Here's some info on mindmapping:

Mind Map Wikipedia Entry

Here's FreeMind, an open source, java software package that will help you implement it:

FreeMind

Thursday, March 4, 2010

Quote from David Kekich and others.

Anxiety is caused by a lack of control, organization, preperation, and action.
-David Kekich

Think like a man of action, act like a man of thought.
-Henry Bergson

It is not enough to stare up the steps; we must step up the stairs.
-Vaclav Havel

Thomas Edison and Bill Maher

Here are a couple more quotes:

"People would rather be nice than right, rather be sensitive than be true. Well, being nice and sensitive are important, but they're not more important than being right; they're not more important than the truth."
Bill Maher

"Opportunity is missed by most people because it is dressed in overalls and looks like work"
Thomas Edison

Favorite Quotes

I was out to dinner with some friends and was going through a few of my favortie quotes. I realized that I don't have any posted, so here they are:

*All comments are written in first person by Ike.
"Reduce everything to it's essence, so that form harmonizes with function"
Cris Kobryn
Chair, U2 Partners' UML 2.0 Submission Team

"If we pursue the parsimony koan to its full intent, we should find UML modeling projects to be as enjoyable as we found finger-painting and drawing classes in grammer school."
Cris Kobryn
Chair, U2 Partners' UML 2.0 Submission Team

"Do not rely on Rigid, Inefficient Processes (RIP)."
Steve McConnell
Software Project Survival Guide

"Early in the project you can have firm cost and schedule targets or a firm feature set, but not both."
Steve McConnell
Software Project Survival Guide

"There is a word for software that cannot be changed after delivery. That word is hardware."
Ward Cunningham
co-Inventor of Extreme Programming
Preface to Extreme Programming Pocket Guide

"The problem with quick and dirty is that dirty remains long after quick is forgotten."
Unknown

"As a programmer writing computer programs, you must develop a very special relationship with a shadowy being who lurks just beyond the periphery of your vision. At the same time needy, confused, angry, and malicious, that person is known to you only as The User."
Charles Petzold
Programming in the Key of C#

"Some people hold the view that the UML should be used to create a design that is independent of the programming language that's used for implementation. Others believe that language-independent design is an oxymoron, with a strong emphasis on the moron."
Martin Fowler
UML Distilled
I agree with this on most topics, not just on software design, ie database design, T-SQL authoring, multi-platform development. -Ike

"Question: What is the difference between a methodologist and a terrorist?
Answer: You can negotiate with a terrorist."
Martin Fowler
UML Distilled

"You should use iterative development only on projects that you want to succeed.
Perhaps that's a bit glib, but as I get older, I get more aggressive about using iterative development."
Martin Fowler, espousing Extreme Programming
UML Distilled

"Often, you'll find that the more stable packages tend to have a higher proportion of interfaces and abstract classes."
Martin Fowler, espousing Polymorphism
UML Distilled


"The real moments of discovery aren't when someone shouts "Eureka", but when someone mumbles, "Hmmm....that's wierd." "
Carl Sagan

"Too often, however, the metaphor is used to assert that the child class inherits the internals of the parent class, an allusion to the fact that biological organisms inherit the DNA structures of their parents. This is a poor and potentially misleading use of the metaphor....
The desire for a child class to inherit internals of its parent classes can be better accommodated if we change the notion of inheritance from DNA to assets. It has been noted that an object has access to whatever resources it needs to fulfill its behavioural expectations. "
David West
Author of Object Thinking

"The best programmers are up to 28 times better than the worst programmers, according to "individual differences" research. Given that their pay is never commensurate, they are the biggest bargains in the software field."
Robert L. Glass
Author of Facts and Fallacies of Software Engineering

Friday, February 12, 2010

Agile Development - Not A License to Skip Steps


We've all been part of software development projects that didn't have a very good project plan. I believe that it is still possible for a project to be successful without a project plan, but it introduces unnecessary risk. A properly agreed upon project plan will not eliminate that risk, but it will greatly reduce it. Proejects without planning documents are about 50% successful. When they have a plan, they are about 90% successful. That is independent of developer talent.

Often as agile developers, we skip some of the SDLC steps. Agile does not mean that SDLC steps are skipped. It just means that they are compressed into shorter, more frequent release cycles.

Here are the SDLC steps that are mandatory:

Planning/Design
Development
Review
Testing
Rollout
Support Plan

The two steps that are most frequently skipped or inappropriately shortened are arguably the most important: planning and testing. This is just a friendly reminder to review how those steps are implemented and delivered.

Wednesday, January 6, 2010

Programmers Are Like Boy Scouts On A Hike


I was reading "The Goal", by Eliyahu Goldratt, when I came across an analogy that was familiar. I'm a scout leader, and so get plenty of opportunities to watch boy scouts hike on trails. I've noticed that when each one walks at their own pace, some boys will get to the end of the trail far faster than the slowest boy. If it's a two hour hike, one boy will finish in 90 minutes, while the slowest boy will finish in 2 1/2 hours.

If this were a software development department, that would mean that some developers would finish far ahead of others. The entire project would be delivered according the pace of the slowest developer.

When Boy Scouts march as a troop, the most amazing thing happens. They work together as a team. Two hour hikes are often completed between 1 3/4 hours and 2 hours. That means that the team environment compensates for the slowest guy far more than it slows down the fastest guy.

For a software development department, this increase of productivity is immediate. As the team gets used to working together, they get faster and faster, often sprinting and running towards finish lines. Each software project is delivered on or before the deadline, as long as we are implementing the principles of team development.

Now if I could just get the developers to "Be Prepared", we'd be all set.