Gregory's profileStop Making SensePhotosBlogNetwork Tools Help

Gregory Beamer

Occupation
Location
Interests
Microsoft MVP and consumate computer geek, living on the bleeding edge (early alphas are fun :-0). Married, with four daughters(oldest is 6; do the math).
There are no music lists on this space.

Stop Making Sense

Use your brain, nobody else will!
18 December

Caroline Pryce Walker Conquer Childhood Cancer Act Funding Update

If you have not seen my earlier post on the Caroline Pryce Walker Conquer Childhood Act (entitled The Caroline Pryce Walker Conquer Childhood Shill Game), this post is a follow up for that one.

The latest news for 2010 is as follows, according to Cure Search

  • $3 million for the CDC to set up a childhood cancer registry
  • $1 for HHS to provide outreach, resource and program services for children with cancer and their families
  • $1.6 million for pediatric cancer research in the defense appropriation bill (not sure why it is here)
  • $4 extra in the NCI budget for childhood cancer

Summary

$30,000,000 promised
$  9,600,000 delivered (32%)
---------------------------------
$20,400,000 short (68%)

Funding expected to date

$60,000,000 promised
$  9,600,000 delivered (16%)
---------------------------------
$50,400,000 short (84%)

 

I wonder if we will have to have someone in Washington fighting each year to get a small portion of what was promised? If you go back to my earlier post, you see this quote from the appropriations committee:

The National Cancer Institute reports that it is meeting the funding
level identified for pediatric cancer research in the Caroline Pryce
Walker Conquer Childhood Cancer Act of 2008 within its base budget. The
conferees commend NCI for its attention to this issue.

It takes government math to make $4 million equal $26 million (considering the defense appropriation bill was not included at the time the statement was made). And you want to hand over your lives to these people?

Peace and Grace,
Greg

Twitter: @gbworld

Visual Studio 2010 Delayed

Microsoft announced yesterday that the release for Visual Studio 2010 was going to be delayed due to some performance issues. You can read about it on Soma’s and Guthrie’s blogs (links below):

The blogs both announce a Release Candidate build in February, which will push Visual Studio 2010 back at least a few weeks from its March 22, 2010 release date. How far back will depend on feedback from people testing the release.

Peace and Grace,
Greg

Twitter: @gbworld

14 December

Understanding Data in .NET

I have seen quite a few posts lately about the data objects in .NET. One of the latest ones was this:

Is it correct to say that when you use ASP.NET you use SqlDataSource but
when you use Windows forms you use SqlDataAdapter.

Time for a primer.

Data Basics

In order to work with data in any paradigm, you need a few things.

  1. A means of connecting to the data source
  2. A means of querying the data source
  3. A container object to hold the result(s) from the data source query

In ADO.NET, as with ADO before it, #1 is solved with a connection object and #2 is solved with a Command object. The final part can be solved with a wide variety of objects. Here are some examples:

  • DataSet
  • Entity Framework objects
  • LINQ objects
  • Custom objects (generally filled with something like a DataReader)

So, connection, command and a container. Pretty simple, right? But what about DataSource objects or DataReaders? And where do Transaction objects fit in? In order to answer this question,  let’s first look at storing and moving data, no matter what its form is.

Streams and Endpoints

In applications, we are generally concerned with two aspects: Behavior and State. If we over-generalize, state is the information we are working with, while behavior is how me alter state to fulfill the goals of the application. With data, however, we tend to focus on state and allow Microsoft to worry about behavior. Let’s take a look at streams and endpoints for a second before we drop down into data specifics.

The Endpoint:
The most obvious endpoint in any application that works with data is the data source. In general, this is a database, but we can also store in flat files, XML files, etc. The important point about this particular endpoint is it is designed to persist between sessions, so we can find the information the next time a user wants to access it.

There are other types of endpoints, however. Any time a piece of data is held for any length of time, we have an endpoint. This means our objects serve as a type of “in memory” endpoint.

Streams
A stream is a means of getting objects from one endpoint to another. Some streams are obvious, like the MemoryStream. Some semi-obvious, like the StreamReader or StreamWriter used for text files. Others are not so obvious. The DataReader, for example, is a stream type of object. It acts as a “firehose” cursor (think one direction and very fast) for data.

If we wanted to picture endpoints and streams visually, it might look like the diagram below. Notice how the DataReader works as a Stream from a Database to a DataSet or custom objects.

Endpoints_Streams

The takeaway here is endpoints are where we store “data”, either temporarily (use in our current session) or persistent (use across sessions). This is an oversimplification, of course, but it works to get us to .NET data objects.

Working with Data in ADO.NET

You will notice ADO.NET spans a couple of namespaces. There is a general namespaces System.Data and specific namespaces, like System.Data.SqlClient, System.Data.OleDb and System.Data.Odbc. If you move to LINQ or EF, there are additional namespaces that, while not directly ADO.NET, have a lot of ties into ADO.NET. I am only going to focus on the namespaces with System.Data in this section. Let’s map this out

System.Data

  • Common enumerations
  • Common exceptions
  • DataSet “container” classes – endpoints
  • Interfaces for data classes (this may be the most important part of System.Data)

System.Data.Common

  • Base classes for specific implementations. We are mostly concerned with the following:
    • connection
    • command
    • adapter

System.Data.{Specific}

For our purposes, {Specific} will mean one of the following namespaces, which contain specific implementations for the base classes in System.Data.Common:

  • System.Data.Odbc
  • System.Data.OleDb
  • System.Data.OracleClient
  • System.Data.SqlClient

And what about System.Data.Linq? LINQ is a bit of a special cases, as it is a wrapper for the underlying ADO.NET goodness. We will touch wrapper classes when we get to {Type}DataSource in the ASP.NET discussion. Unfortunately, I will have to get into specifics for how LINQ wraps ADO.NET in another entry.

The DataReader

I will cover the Data Reader first, as it is one of the simplest to understand. We will assume we are filling a collection of custom objects, but we could be filling rows in a DataSet (this will be important in a bit). Here is a diagram of our retrieval and storage in memory:

FillingACustomCollection

Let’s make sure we understand this:

  • We need a connection to get to the database
  • We need a command to run
  • The database is one endpoint
  • The collection is another
  • The DataReader serves as a stream from the database (endpoint 1) to the collection (end point 2)

Here is how it looks in code (overly simplistic, of course):

//Customer
public class Customer
{
    public string FName { get; set; }
    public string LName { get; set; }

    public Customer()
    {
    }
}

//CustomerCollection
public class CustomerCollection : Dictionary<string,Customer>
{
}

Now some data access code so we can see the Reader in action:

CustomerCollection customers = new CustomerCollection();
string connectionString = GetConnectionString();
string commandString = "Select TOP 2 FName, LName From Customer";

SqlConnection connection = new SqlConnection(connectionString);
SqlCommand command = new SqlCommand(commandString, connection);

try
{
    connection.Open();
    SqlDataReader reader = command.ExecuteReader();

    while (reader.Read())
    {
        Customer customer = new Customer();
        customer.FName = reader["FName"];
        customer.LName = reader["LName"];
        customers.Add(customer.LName + ", " + customer.FName
            , customer);
    }

}
finally
{
    connection.Dispose();
}

Pretty simple. And we can see that we need to read (records, lines, bytes) from a stream object (in this case records from the DataReader) to get them from one endpoint to another. I could get a bit more complex and show what is going on underneath the hood, but this is enough to get the concept.

DataSets

The DataSet seems much simpler, as we don’t worry about the stream, right? Let’s flip this one over and look at the code. Note that I am

CustomerDataSet customers = new CustomerDataSet();
string connectionString = GetConnectionString();
string commandString = "GetCustomersWithOrders";

SqlConnection connection = new SqlConnection(connectionString);
SqlCommand command = new SqlCommand(commandString, connection);
command.CommandType = CommandType.StoredProcedure;

SqlDataAdapter adapter = new SqlCommand(command);
adapter.TableMappings.Add("Table", "Customer");
adapter.TablesMappings.Add("Table1", "Order");

try
{
    connection.Open();
    adapter.Fill(customers);
}
finally
{
    connection.Dispose();
}

It appears there is no stream involved, but there is still a DataReader. It is just hidden from us (hidden objects with dotted lines):

DataSet

This “hiding” becomes very important as you get deeper into ASP.NET and how it interacts with ADO.NET.

DataSource Controls

Here is where things get really nasty, as far as understanding goes. The DataSource controls, like SqlDataSource, are wrappers. The way you use them is you drag a DataSource control on a page, set some properties and then bind the DataSource to a control, like a Grid. What it looks like is this:

SqlDataSource

Look at all those hidden objects. In addition, the SqlDataSource is a bit hidden, as you manipulate it in one of two ways.

  • Change the tag in the ASP.NET page (ASPX)
  • Click on the context menu (chevron in upper right hand corner) and go through the dialogs

Some of the underlying objects are exposed when you use this object programmatically. Others are partially exposed, meaning you can change some properties of the object.

Answering the Question

Now for the short answer to this question:

Is it correct to say that when you use ASP.NET you use SqlDataSource but
when you use Windows forms you use SqlDataAdapter.

No, it is not correct. Technically, if you want to include the correct libraries, you can use the SqlDataSource with a windows forms library, as well. What is true is you see the SqlDataSource used in many drag and drop examples. It makes things easier, if you can fit in the box, as these are the steps.

  1. Drag a GridView on the page
  2. Drag a SqlDataSource on the Page
  3. Configure the SqlDataSource using the wizard
    1. Add a connection string
    2. Add a command
  4. Configure the GridView
    1. Set the SqlDataSource as the source
    2. Configure for empty result set to be safe
    3. (optionally) Add formatting to make the GridView look better

You don’t have to write any code, but a lot of code is working to make this magic work, as illustrated in the last section. This is fine as long as you don’t need to completely control the underlying objects.

This is a good first article and should show how we build layers on top of layers, constantly hiding things. This makes things easier for the newbie developer and can work in many cases. Eventually, however, you will find an exercise that requires you get out of this box.

Peace and Grace,
Greg

Twitter: @gbworld

10 December

Osteoporosis drug may reduce risk of breast cancer?

This article is fresh off the presses. The Women’s Health Initiative, the group that found hormone replacement therapy was bad, has another shocker. Taking an osteoporosis drug reduces the risk of breast cancer by 32%. Here is the hype, er news, in the press release, er article, on reuters:

The analysis from a segment of the more than 150,000 generally healthy post-menopausal women in the WHI study found that those taking Merck & Co's Fosamax, or other bisphosphonates, had 32 percent fewer cases of invasive breast cancer than women who did not use the osteoporosis medicines, researchers found.

Sounds promising. 150,000 women. 32% fewer cases of breast cancer. That is pretty significant, right? This means instead of 192,000 women getting breast cancer, the rate will reduce to about 127,000 right? No, it does not. Read further:

Studying 2,816 participants who were using bisphosphonates when they entered the WHI program, researchers found that only 64 women developed breast cancer. That translates into 32 percent fewer breast cancers in women using bisphosphonates compared with women who did not use them, researchers said.

Oh, so the entire study was 150,000 women, but only 2,816 were using alendronate. And, of those 64 got breast cancer over the length of the study. This accounts for less than 2.3% of women taking alendronate. Divide that by the number of years of the study (not-mentioned) and you see it is a small number. Since it is a 32% relative risk, this means the absolute benefit from taking alendronate is less than 1 person in one hundred. At numbers this low, we very well might be dealing with a statistical fluke, as we often see these types of rises in numbers when we compare nothing to a placebo in a control group study. Not striking enough for me to put that drug in my body, if I were a woman and did not have Osteoporosis.

But what’s the risk of taking Osteoporosis medicine? In a long term study of alendronate, we find nearly a third of the participants that completed the full study had a serious clinical event during the study, with about 7% with an event serious enough to warrant discontinuation of the study. If we take this to the types of events expected from alendronate (primarily GI), we end up with some where between 15.4% and 30.2% (note that the rates are spread across two dosage groups, which is why there is such a wide spread).

In abosolute terms, less than 1 women out of 100 will benefit from alendronate, as far as breast cancer is concerned, but using the best figures we have, about 15% will experience a serious condition as a result of taking the drug.

Am I stating that alendronate should not be used for women at high risk for cancer? Certainly not. Just that you need to look at both relative and absolute benefit when you are making a decision on what meds to put in your body.

Peace and Grace,
Greg

Twitter: @gbworld

ASP.NET Tricks: Dealing with the Back Button

Questions about the back button come up all of the time. A user gets a result set and then clicks back and wonders why their activities are not reflected when they hit back. Or they fill in a form and then hit back and submit again and wonder why there are two records (after all, the app is supposed to find their record after submission).

The issue with the back button is client side cache. One a page is hit, the rendered HTML is stored on the client side. If the user hits back, and has the default settings for their browser, it pulls from cache when they hit back and does not re-request the page. This causes a lot of problems with some applications.

First, let’s look at the browser. When you first open Internet Explorer (one example) and look at the caching options, they look like this:

TempFiles

What this states is the browser will decide automatically whether to pull from cache or go out and get the page. What IE will do is only request the page when it cannot pull from cache, or you have not browsed the page in quite some time, etc.

Disabling the Cache

I guess you could tell all of your users to change their browser settings and conquer this once and for all. :-)

Programmatically, the cache is disabled by the following line:

Response.Cache.SetCacheability(HttpCacheability.NoCache);

Once you have this line in your Page_Load, the page will reload each time back is hit. This is fine in many instances, as it will try to reset everything up to the state when you first requested. But on a multi-part form, you can end up with trouble still, depending on ViewState settings, etc. What this does is send a “do not cache” header to the client.

Examining the Request in Fiddler, we see the following:

Fiddler1

Compare this to when the line is commented out:

Fiddler2

Disabling the Back Button

This is often the most sane choice with a very complex flow. It is rather easy to facilitate with JavaScript.

<script type="text/javascript">
    history.go(+1);
</script>

This is not actually disabling the button, so don’t use this in conjunction with the Response expiring method, or you can end up with this:

WebExpired

Of course sometimes this is not so bad, right? :-)

Hiding the Back Button

This one is not so useful with Internet users, but is very useful with internal users. What you do, when the app is hit, is open another page in another window that does not have a back button.

<script type="text/javascript">

    function PopWindow()
    {
        window.open("default2.aspx",'Popup','toolbar=0,location=0,menubar=0');
    }

</script>

and

<body onLoad ="PopWindow()">

This is the most effective, as the user does not have button, but the user can still hit the backspace key, so you need to add one more thing.

<script type="text/javascript">
    function checkShortcut()
    {
        if (event.keyCode == 8) {
            return false;
        }
    }
</script>

and

<body onkeydown="return checkShortcut()">

Here is a script someone else posted here. It is designed to work in IE7, which many forms of backspace button killing do not.

<script type="text/javascript">
    function killBackSpace(e) {
        e = e ? e : window.event;
        var k = e.keyCode ? e.keyCode : e.which ? e.which : null;
        if (k == 8) {
            if (e.preventDefault)
                e.preventDefault();
            return false;
        };
        return true;
    };
    if (typeof document.addEventListener != 'undefined')
        document.addEventListener('keydown', killBackSpace, false);
    else if (typeof document.attachEvent != 'undefined')
        document.attachEvent('onkeydown', killBackSpace);
    else {
        if (document.onkeydown != null) {
            var oldOnkeydown = document.onkeydown;
            document.onkeydown = function(e) {
                oldOnkeydown(e);
                killBackSpace(e);
            };
        }
        else
            document.onkeydown = killBackSpace;
    }
</script>

But this one comes with a serious caveat. If there is a textbox on the page, the user may need backspace, so you end up having to add a handler only to controls that are not textboxes. To overcome this, you have to addEventListeners for the individual controls that need the backspace that point to a routine that will return true. Unfortunately, I don’t have time to play with this right now.

Final Notes

One of the issues with all of these methods is newer browsers come out that no longer respect the old rules. The fact a rather complex script that adds event handlers is needed for IE7 and above is a prime example. One of the best things you can do to avoid the back button blues is design applications that don’t degrade when the back button is hit. ASP.NET MVC gives some good practices in this area, as the routing is through the query string, which means the user will redraw the form when they hit back if you expire cache. You can also work with ASP.NET, but you have to be sure that you do not end up with extremely complex, multi-part forms that have no means of returning state. ViewState can be your ally in many instances, so don’t be afraid to use it if you end up with this complexity.

I hope this helps you out.

Peace and Grace,
Greg

Twitter: @gbworld

 
Photo 1 of 64