Mostrar mensagens com a etiqueta C#. Mostrar todas as mensagens
Mostrar mensagens com a etiqueta C#. Mostrar todas as mensagens

segunda-feira, agosto 25, 2008

JSON - Javascript Object Notation

JSON (JavaScript Object Notation - Notação de Objetos JavaScript) é uma formatação leve de troca de dados. Para seres humanos, é fácil de ler e escrever. Para máquinas, é fácil de interpretar e gerar. Está baseado em um subconjunto da linguagem de programação JavaScript, Standard ECMA-262 3a Edição -Dezembro - 1999.
JSON é em formato texto e completamente independente de linguagem, pois usa convenções que são familiares às linguagens C e familiares, incluindo C++, C#, Java, JavaScript, Perl, Python e muitas outras. Estas propriedades fazem com que JSON seja um formato ideal de troca de dados.

JSON está constituído em duas estruturas:

  • Uma coleção de pares nome/valor. Em várias linguagens, isto é caracterizado como um object, record, struct, dicionário, hash table, keyed list, ou arrays associativas.
  • Uma lista ordenada de valores. Na maioria das linguagens, isto é caracterizado como uma array, vetor, lista ou sequência.

Estas são estruturas de dados universais. Virtualmente todas as linguagens de programação modernas as suportam, de uma forma ou de outra. É aceitavel que um formato de troca de dados que seja independente de linguagem de programação se baseie nestas estruturas.

Em JSON, os dados são apresentados desta forma:

Um objeto é um conjunto desordenado de pares nome/valor. Um objeto começa com { (chave de abertura) e termina com } (chave de fechamento). Cada nome é seguido por : (dois pontos) e os pares nome/valor são seguidos por , (vírgula).

Uma array é uma coleção de valores ordenados. O array começa com [ (conchete de abertura) e termina com ] (conchete de fechamento). Os valores são separados por , (vírgula).

Um valor (value, na imagem acima) pode ser uma cadeia de caracteres (string), ou um número, ou true ou false, ou null, ou um objeto ou uma array. Estas estruturas podem estar aninhadas.

Uma string é uma coleção de nenhum ou mais caracteres Unicode, envolvido entre aspas duplas usando barras invertidas como caracter de escape. Um caracter está representando como um simples caracter de string. Uma cadeia de caracteres é parecida com uma cadeia de caracteres em C ou Java.

Um número é similar a um número em C ou Java, exceto quando não se usa os números octais ou hexadecimais.

Espaços em branco podem ser inseridos em quanlquer parte dos símbolos. Exceto pequenos detalhes de codificação, a linguagem é completamente descrita.




Podem consultar exemplos de JSON em http://www.json.org/json-pt.html

AjaxPro - Ajax for Microsoft.NET Framework 2.0 and 1.1

Ajax.NET Professional

Microsoft.NET Framework 2.0 and 1.1

There are two new screen casts available to show how to use AjaxPro:

  • Lesson 1 How to change a feedback form to use AjaxPro
  • Lesson 2 How to use asynchronous methods to prevent web browser blocking

Below you will find some example web pages that are using Ajax.NET to get rid of the postback in typical ASP.NET applications:



Mais info aqui.

sexta-feira, agosto 22, 2008

Conceitos C#: Value Types vs Reference Types

Uma grande questão que me surgiu nos últimos tempos está relacionado como é feita a manipulação de tipos de referências de variáveis, se os ponteiros funcionavam como no C/C++.

Ora, encontrei um excelente artigo que explica muito bem como funciona esse sistema de referências. Basicamente há que ter em noção que em C# existem 2 tipos de variáveis: Structs e Classes. São 2 tipos muito semelhantes. A grande diferença tem a haver com o facto das Structs serem um value type e as Classes serem um reference type, ou seja, um value type reserva memória para o valor da variável enquanto que um referente type aloca memória para a variável e para a instância. Basicamente cria uma referência para o valor daquela variável.

Sigam de perto este muito bom artigo de Joseph Albahari, que podem encontrar aqui.


C# Concepts: Value vs Reference Types

Joseph Albahari

Introduction

One area likely to cause confusion for those coming from a Java or VB6 background is the distinction between value types and reference types in C#. In particular, C# provides two types—class and struct, which are almost the same except that one is a reference type while the other is a value type. This article explores their essential differences, and the practical implications when programming in C#.

This article assumes you have a basic knowledge of C#, and are able to define classes and properties.

First, What Are Structs?

Put simply, structs are cut-down classes. Imagine classes that don’t support inheritance or finalizers, and you have the cut-down version: the struct. Structs are defined in the same way as classes (except with the struct keyword), and apart from the limitations just described, structs can have the same rich members, including fields, methods, properties and operators. Here’s a simple struct declaration:

struct Point
{
private int x, y; // private fields

public Point (int x, int y) // constructor
{
this.x = x;
this.y = y;
}

public int X // property
{
get {return x;}
set {x = value;}
}

public int Y
{
get {return y;}
set {y = value;}
}
}

Value and Reference Types

There is another difference between structs and classes, and this is also the most important to understand. Structs are value types, while classes are reference types, and the runtime deals with the two in different ways. When a value-type instance is created, a single space in memory is allocated to store the value. Primitive types such as int, float, bool and char are also value types, and work in the same way. When the runtime deals with a value type, it's dealing directly with its underlying data and this can be very efficient, particularly with primitive types.

With reference types, however, an object is created in memory, and then handled through a separate reference—rather like a pointer. Suppose Point is a struct, and Form is a class. We can instantiate each as follows:

Point p1 = new Point(); // Point is a *struct*
Form f1 = new Form(); // Form is a *class*

In the first case, one space in memory is allocated for p1, wheras in the second case, two spaces are allocated: one for a Form object and another for its reference (f1). It's clearer when we go about it the long way:

Form f1; // Allocate the reference
f1 = new Form(); // Allocate the object

If we copy the objects to new variables:

Point p2 = p1;
Form f2 = f1;

p2, being a struct, becomes an independent copy of p1, with its own separate fields. But in the case of f2, all we’ve copied is a reference, with the result that both f1 and f2 point to the same object.

This is of particular interest when passing parameters to methods. In C#, parameters are (by default) passed by value, meaning that they are implicitly copied when passed to the method. For value-type parameters, this means physically copying the instance (in the same way p2 was copied), while for reference-types it means copying a reference (in the same way f2 was copied). Here is an example:

Point myPoint = new Point (0, 0); // a new value-type variable
Form myForm = new Form(); // a new reference-type variable

Test (myPoint, myForm); // Test is a method defined below

void Test (Point p, Form f)

{
p.X = 100; // No effect on MyPoint since p is a copy
f.Text = "Hello, World!"; // This will change myForm’s caption since
// myForm and f point to the same object
f = null; // No effect on myForm
}

Assigning null to f has no effect because f is a copy of a reference, and we’ve only erased the copy.

We can change the way parameters are marshalled with the ref modifier. When passing by “reference”, the method interacts directly with the caller’s arguments. In the example below, you can think of the parameters p and f being replaced by myPoint and myForm:

Point myPoint = new Point (0, 0); // a new value-type variable
Form myForm = new Form(); // a new reference-type variable

Test (ref myPoint, ref myForm); // pass myPoint and myForm by reference

void Test (ref Point p, ref Form f)

{
p.X = 100; // This will change myPoint’s position
f.Text = “Hello, World!”; // This will change MyForm’s caption
f = null; // This will nuke the myForm variable!
}

In this case, assigning null to f also makes myForm null, because this time we’re dealing with the original reference variable and not a copy of it.

Memory Allocation

The Common Language Runtime allocates memory for objects in two places: the stack and the heap. The stack is a simple first-in last-out memory structure, and is highly efficient. When a method is invoked, the CLR bookmarks the top of the stack. The method then pushes data onto the stack as it executes. When the method completes, the CLR just resets the stack to its previous bookmark—“popping” all the method’s memory allocations is one simple operation!

In contrast, the heap can be pictured as a random jumble of objects. Its advantage is that it allows objects to be allocated or deallocated in a random order. As we’ll see later, the heap requires the overhead of a memory manager and garbage collector to keep things in order.

To illustrate how the stack and heap are used, consider the following method:

void CreateNewTextBox()
{
TextBox myTextBox = new TextBox(); // TextBox is a class
}

In this method, we create a local variable that references an object. The local variable is stored on the stack, while the object itself is stored on the heap:

The stack is always used to store the following two things:

  • The reference portion of reference-typed local variables and parameters (such as the myTextBox reference)
  • Value-typed local variables and method parameters (structs, as well as integers, bools, chars, DateTimes, etc.)

The following data is stored on the heap:

  • The content of reference-type objects.
  • Anything structured inside a reference-type object.

Memory Disposal

Once CreateNewTextBox has finished running, its local stack-allocated variable, myTextBox, will disappear from scope and be “popped” off the stack. However, what will happen to the now-orphaned object on the heap to which it was pointing? The answer is that we can ignore it—the Common Language Runtime’s garbage collector will catch up with it some time later and automatically deallocate it from the heap. The garbage collector will know to delete it, because the object has no valid referee (one whose chain of reference originates back to a stack-allocated object).[1] C++ programmers may be a bit uncomfortable with this and may want to delete the object anyway (just to be sure!) but in fact there is no way to delete the object explicitly. We have to rely on the CLR for memory disposal—and indeed, the whole .NET framework does just that!

However there is a caveat on automatic destruction. Objects that have allocated resources other than memory (in particular “handles”, such as Windows handles, file handles and SQL handles) need to be told explicitly to release those resources when the object is no longer required. This includes all Windows controls, since they all own Windows handles! You might ask, why not put the code to release those resources in the object’s finalizer? (A finalizer is a method that the CLR runs just prior to an object’s destruction). The main reason is that the garbage collector is concerned with memory issues and not resource issues. So on a PC with a few gigabytes of free memory, the garbage collector may wait an hour or two before even getting out of bed!

So how do we get our textbox to release that Windows handle and disappear off the screen when we’re done with it? Well, first, our example was pretty artificial. In reality, we would have put the textbox control on a form in order to make it visible it in the first place. Assuming myForm was created earlier on, and is still in scope, this is what we’d typically do:

myForm.Controls.Add (myTextBox);

As well as making the control visible, this would also give it another referee (myForm.Controls). This means that when the local reference variable myTextBox drops out of scope, there’s no danger of the textbox becoming eligible for garbage collection. The other effect of adding it to the Controls collection is that the .NET framework will deterministically call a method called Dispose on all of its members the instant they’re no longer needed. And in this Dispose method, the control can release its Windows handle, as well as dropping the textbox off the screen.

All classes that implement IDisposable (including all Windows Forms controls) have a Dispose method. This method must be called when an object is no longer needed in order to release resources other than memory. There are two ways this happens:
- manually (by calling Dispose explicitly)
- automatically: by adding the object to a .NET container, such as a Form, Panel, TabPage or UserControl. The container will ensure that when it’s disposed, so are all of its members. Of course, the container itself must be disposed (or in turn, be part of another container).
In the case of Windows Forms controls, we nearly always add them to a container – and hence rely on automatic disposal.

The same thing applies to classes such as FileStream—these need to be disposed too. Fortunately, C# provides a shortcut for calling Dispose on such objects, in a robust fashion: the using statement:

using (Stream s = File.Create ("myfile.txt"))

{

...

}

This translates to the following code:

Stream s = File.Create ("myfile.txt");

try

{

...

}

finally

{

if (s != null) s.Dispose();

}

The finally block ensurse that Dispose still gets executed should an exception be thrown within the main code block.

segunda-feira, agosto 18, 2008

ASP.NET: DataSet vs DataReader (Pt. 03/03)

DataTables vs. DataSets
A number of commenters brought up mentions of DataTables, correctly pointing out that DataTables offer better efficiency than DataSets, but with more features than the DataReader. For example, one comment read:

I mostly use DataTables (sometimes DataReader) since pages usually deal with a single table of data. It is quite upsetting to find books and tutorials forever teaching the use of DataSet together with DataAdapter. I wonder how many know the DataAdapter works with DataTables stand alone.
-- icelava
Yes, it is true that the DataTable is more efficient than the DataSet. The DataSet is, after all, a set of DataTables; you can programmatically access the DataSet's collection of DataTables through its Tables property. And DataTables offer the functionality not found in DataReaders: DataTables support random access, can be sorted and filtered using DataViews, their contents can modified through insertions, updates, and deletes.

So should you use DataTables in lieu of DataSets? Sure, if you can. A DataTable doesn't support all of the features of a DataSet, so they might not be an appropriate choice. (For example, in .NET 1.x DataTables cannot be natively serialized into XML; additionally, if you need to represent relationships among multiple DataTables, you'll need to use a DataSet.) What it all comes back - and this was my thesis from the original Why I Don't Use DataSets article - is that you should use the right object for the job at hand. Each data object has a time and place - my contention is that DataSets (and DataTables) have limited use in ASP.NET applications.

Returning DataSets from Web Services
In my original article I mentioned that one use of DataSets is a conduit for returning database data from an XML Web Service. Since DataSets can trivially be serialized into XML, developers are quick to use DataSets when returning database information from a Web service. In fact, a number of commenters mentioned this:

If you're using webservices in your application that return result sets, then you would want to use a dataset to hold these result sets.
-- Wessam Zeidan
While DataSets are an easy way to return data, I think they are less than ideal for a couple of reasons. First, they add a lot of bloat to the returned XML payload since DataSets return not only the data they contain but also the data's schema. If you are only returning a small number of records, the payload's size can be dominated by the schema information. Second, DataSets have the air of being platform specific. While it's true that an XML serialized DataSet is, after all, just XML and therefore can be processed by a client on any platform, it still has a platform-specific feel to it since the resulting XML markup is dictated by Microsoft. A .NET client can automatically deserialize a DataSet's XML payload returned from a Web service back into a DataSet, thereby making DataSets an easy and attractive option. Clients using other platforms, however, will find they have to invest a lot more effort in order to work with the server's returned serialized DataSet.

The solution? Create a serializable, custom business object and have your Web services return an array of these custom objects. The overall payload size will be significantly less and the returned payload will be more inviting to clients not using .NET. One commenter summed up this sentiment nicely with:

For me, DataSets are too platform specific to use in Web Services. I prefer returning XML serialized arrays of objects. It may require my consumer to do a little bit more work, but it ensures that I have a wider base of consumers.
-- Scott
The one downside of returning custom collections from a Web service is that for .NET clients, these custom classes are serialized as classes with public fields as opposed to public properties. When binding a custom collection to a DataGrid or other data Web control, the data binding only allows binding to properties. Fortunately this nuisance is fixed in .NET 2.0. (For more information on the benefits of returning custom collections from Web services as well as how to work around the field/properties pain, be sure to check out the "Binding to Web Services" section of Dino Esposito's Collections and Data Binding article.)

Yes, Using DataReaders You Can Do That, Too!
There were a number of comments from readers who seemed to be using the DataSet because they (incorrectly) believed that the same functionality could not be accomplished through the use of DataReaders. One reader asked: "How would you handle sorting, paging and updating if you fill a DataReader into a DataGrid?" Assuming this commenter was asking about ASP.NET DataGrids, the answers can be found throughout the An Extensive Examination of the DataGrid Web Control article series here on 4Guys. See Part 4 for information on sorting, Part 15 for the low-down on paging, and Part 6 for the scoop on editing.

Additionally, in reading many of the comments in favor of DataSets it appeared that a number of commenters seemed to think that the DataSet was an ideal object for computing aggregates - counts, sums, and so on - or for retrieving two related tables and displaying fields from both. While the DataSet can accomplish these tasks, I'd recommend performing these operations at the database if possible. SQL has a rich set of aggregate functions - COUNT, SUM, MAX, and MIN, to name a few - and a join at the database level is always going to be more efficient than bringing back all of the data from both tables and relating the resulting rows at the ADO.NET layer. (Granted, there is a time and a place for this, such as when working with disconnected data in a desktop application, but I would contend that these features are not often needed in Web applications.)

How Important is Performance?
In my original article one of my main thrusts for not using DataSets was the performance disparity between DataSets and DataReaders. As I cited from A Speed Freak's Guide to Retrieving Data in ADO.NET, when bringing in several hundred or thousands of records, a DataSet can take several seconds to be populated, where as a DataReader still boasts sub-second response times. Of course, these comparisons against several hundred to several thousand records are moot if you are working with a much smaller set of data, say just 10 to 50 records in total. For these smaller sized result sets, the DataSet will only cost you less than a second (although the DataReader still is, percentage-wise, much more efficient).

This gives rise to the question, then, of "How often are you bringing back hundreds of records from the database?" And, more importantly, "Should you be bringing back hundreds (or thousands) of records?" One commenter noted that:

The [Speed Feak] article shows how performance degrades all the way up to 10,000 records... realistically you should never be displaying a client more than 100-200 over the web if not for performance purposes but just readability.
-- Eric Wise
I agree wholeheartedly, but what one "should do" vs. what one is "asked to do" can be two different things. I've had clients in the past who, despite my suggestions, were adamant about having large amounts of data shown on the page, be it a gargantuan DataGrid or a drop-down list with hundreds (or even thousands - eep!) of records. Additionally, many developers, when adding paging support to a DataGrid, either always use the default paging model or implement the default paging model at first with plans to later upgrade it to the custom paging model. Default paging, as you may know, is far less efficient than custom paging because it requires that the entire data to be paged through be brought back for each and every page, even though only a small subset of the data is actually shown. Custom paging is more intelligent - yet more difficult to implement - because it only retrieves the precise subset of data to display for the current page. (For more on default paging see An Extensive Examination of the DataGrid Web Control: Part 15; for information on custom paging, refer to my book, ASP.NET Data Web Controls Kick Start.)

Even if you are able to convince your client to show only a reasonable amount of data per page, and even if you have the foresight and expertise to use custom paging on all of your pageable DataGrids, the performance gain from using DataReaders as opposed to DataSets would make your application snappier and more adept to scale.

What It All Boils Down To: Design/Develop-Time Efficiency vs. Run-Time Efficiency
What the DataReader vs. DataSets argument really comes down to is design- and develop-time efficiency vs. run-time efficiency. As I mentioned in the original Why I Don't Use DataSets article, the DataReader boasts much greater run-time efficiency over the DataSet. But, as numerous readers noted, the DataSet comes with a number of features that are lacking in with the DataReader, thereby reducing the time it takes to code the application.

For read-only display data, Scott may have point. But for Web sites that collect information from the user and pass it back to the database, DataSets (or DataTables) are much more efficient because the data adapters have the update methods already constructed (auto generated code).
-- Dave C

I've ventured down both paths and came to the conclusion to use the DataSet over custom objects for complex data requests. It may be a heav[i]er object, but it's very powerful and very flex[i]ble. If you['re] pulling back a large set of relational or semi-relational data it's extraordinarily convenient and easy to implement. The features and services are just to[o] compelling to ignore.
-- Lynn

The #1 key benefit [of using DataSets] for me, though, is maintainability of the resultant code base and the rapidity that I can modify/add new functionality. Not to mention the fact that most any .NET developer walking-in off the street is going to be familiar with DataSets/DataAdapters....
-- Mike
If you are already familiar with the DataSet and/or working on a team that is familiar with that model, and if optimal run-time performance is not a concern, then you may find the DataSet to be a better tool for the job. Of course, not everyone enjoys the added features of the DataSet. Some, like this commenter, prefer the simplicity and higher degree of control that custom business objects affords:
I totally agree with Scott on this one. The DataSet, although a very novel disconnected design, brings with it a rather complex model to support. The more they work into your architecture, the more cumbersome things can become. That statement comes from using them for things like reading XML into the DataSet and having to do a bunch of customized sorting. The syntax is right down bewildering...

My personal approach is using business objects. There are a lot of reasons they end up being highly valuable. One of those reasons is the ability to port designs into other OO languages like Java. ... I was a huge advocate and had the whole DataSet stuff forced down my throat from a "top 3" consulting firm. I did use them and they are still in my architectures. But, from now on I think I am sticking to good old business objects.

-- David

Conclusion
This article served as a follow-up to my earlier article, Why I Don't Use DataSets in My ASP.NET Applications, addressing a number of comments made by readers in the associated blog entry. Thanks to all those who took the time to comment on my blog! If you'd like to continue this discussion, you can do so at http://scottonwriting.net/sowblog/posts/3867.aspx.


Article written by Scott Mitchell (avaliable Here)

ASP.NET: DataSet vs DataReader (Pt. 02/03)

Introduction
A couple weeks ago (April 19th) I gave a talk to the local San Diego ASP.NET SIG and during my talk I mentioned how I, personally, rarely, if ever, use DataSets in my ASP.NET applications, sticking with the good ol' DataReader instead. Since then I have received a number of emails from attendees asking me why I don't use DataSets. Rather than responding to each questioner individually, I decided to write this article explaining my rationale. Read on to learn why I am a DataReader man all the way.

The Fundamentals of the DataReader
Before I can explain why I choose to use DataReaders over DataSets in my Web applications, it's imperative that we all have an understanding of the fundamentals of both DataSets and DataReaders. These two objects have different roles: DataSets are designed to be a mini-in-memory database whereas a DataReader is designed to be a ferry of data between the database layer and a .NET application.

In ADO.NET a provider is some source of data, and there exist provider-specific classes for working with particular providers. There's the SqlConnection, SqlCommand, SqlDataAdapter, and SqlDataReader classes for working with the SqlClient provider; there's the OleDbConnection, OleDbCommand, OleDbDataAdapter, and OleDbDataReader classes for working with the OleDb provider. Objects that are prefixed by a provider name (Sql, OleDb, Oracle, Odbc, etc.) are provider-specific objects. They are designed to work with the particular provider. A DataReader is one such object (i.e., SqlDataReader, OleDbDataReader, etc.).

To work with data via a DataReader you must first establish a connection to the data store and specify the query to execute. Next, the DataReader is created and acts as a bridge between the .NET application and the data store. For example, you might use code like the following:

' Establish Connection
Dim myConnection as New SqlConnection(connection string)
myConnection.Open()

' Create command
Dim myCommand as New SqlCommand(myConnection, SQL query)

' Create a DataReader e
Dim myReader as SqlDataReader
myReader = myCommand.ExecuteReader()

'Iterate through the results
While myReader.Read()
'... Work with the current record ...
End While

' Close the connection
myConnection.Close()

The DataReader loads one record from the data store at a time. Each time the DataReader's Read() method is called, the DataReader discards the current record, goes back to the database, and fetches the next record in the resultset. The Read() method returns True if a row was loaded from the database, and False if there are no more rows.

DataReaders are connected data objects because they require an active connection to the database. Remember, the DataReader is just a ferry of data between the application and database. Understandably, it cannot ferry information back from the database after the connection has been severed. Furthermore, a DataReader is limited to being read-only and forward-only. That is, the information retrieved from the database cannot be modified by the DataReader, nor can the DataReader retrieve records in a random order. Instead, a DataReader is limited to accessing the records in sequential order, from the first one to the last one, one record at a time.

The Fundamentals of the DataSet
DataSets are a more complex and feature-rich object than DataReaders. Whereas DataReaders simply scuttle data back from a data store, DataSets can be thought of as in-memory databases. Just like a database is comprised of a set of tables, a DataSet is made up of a collection of DataTable objects. Whereas a database can have relationships among its tables, along with various data integrity constraints on the fields of the tables, so too can a DataSet have relationships among its DataTables and constraints on its DataTables' fields.

Unlike the DataReader, a DataSet is a provider-neutral data object. There's no SqlDataSet or OleDbDataSet - just a plain, ol' DataSet. It's the responsibility of the provider's DataAdpater object to translate a particular provider's data into the provider-neutral DataSet. The following code snippet illustrates how to populate a DataSet with data from a SQL query.

' Establish Connection
Dim myConnection as New SqlConnection(connection string)
myConnection.Open()

' Create command
Dim myCommand as New SqlCommand(SQL query, myConnection)

' Create the DataAdapter
Dim myDataAdapter as New SqlDataAdapter(myCommand)

' Create the DataSet
Dim myDataSet as New DataSet

' Fill the DataSet
myDataAdapter.Fill(myDataSet)

' Close the connection
myConnection.Close()

'... Work with the contents of the DataSet ...

As the code snippet shows, the DataAdapter's Fill() method populates the DataSet with the results of the specified query. Behind the scenes, the DataAdapter is using a DataReader to read in the results of the query and fill the DataSet. The DataSet is a disconnected data object. Once the DataSet has been filled, the connection can be closed and the DataSet's contents can still be examined and manipulated.

Since a DataSet represents a separate, disconnected collection of data, it's no surprise that the DataSet's data is both editable and can be accessed randomly, two traits not exhibited by the DataReader. Additionally, the DataSet has some powerful XML-related capabilities. For example, you can serialize a DataSet into XML through its WriteXml() method; conversely, you can populate a DataSet from a properly formatted XML stream using the DataSet's ReadXml() method.

The Tradeoff Between the DataSet and DataReader
Regardless of whether or not you bring back database data using a DataSet or DataReader, you can display the underlying data in a DataGrid, DataList, or Repeater using the exact same code. Namely, you set the data Web control's DataSource property to the DataReader or DataSet and then call the Web control's DataBind() method. ASP.NET makes working with data so easy that ASP.NET developers might not give pause and think about what is the best data object to use. All things being equal, it doesn't really matter which data object you use.

But not all things are equal. Clearly there is a major difference in features supported between the DataReader and DataSet, so it's only logical that there be an inverse in the tradeoff between the two objects' performance. Simply put, the DataSet's increased feature set makes it a less performant choice for reading data than the DataReader.

According to A Speed Freak's Guide to Retrieving Data in ADO.NET, the DataReader is roughly thirty times more performant than the DataSet. For large amounts of data being brought back - several hundred or several thousand records - the absolute time differences between accessing data with these two objects can be quite pronounced. The graph below, for example, plots the results from A Speed Freak's Guide to Retrieving Data in ADO.NET for 100 to 1,000 retrieved records using a DataSet (the pink line) and a DataReader (the dark blue line). As the data shows, for retrieving 1,000 records the DataSet is more than 30 times slower than the DataReader (8.89 seconds vs. 0.29 seconds). Eep.


Be sure to read A Speed Freak's Guide to Retrieving Data in ADO.NET for the actual numbers for test runs between 1 to 100 records, 100 to 1,000 records, and 1,000 to 10,000 records, along with the test conditions used. In addition to examining the differences between the DataSet and DataReader, the article compares the performance of the SqlClient provider vs. the OleDb provider when accessing data from a SQL Server 2000 database.

Additional statistics can be found at Performance Comparison: Data Access Techniques, which compares the DataSet and DataReader against a number of common data access scenarios. The end result is that the DataReader is more performant than the DataSet, although this particular article's results do not show as large a performance difference between these two data objects as the Speed Freak article does. Also, the article notes:

In all of the preceding tests, we saw that DataReader outperformed DataSet. As mentioned earlier, the DataReader offers better performance because it avoids the performance and memory overhead associated with the creation of the DataSet. ... The DataReader is a better choice for applications that require optimized read-only and forward-only data access. The sooner you load the data off the DataReader, close the DataReader, and close the database connection, the better performance you get.

When is a DataSet Useful?
Despite the DataSet's performance limitations, there is a time and a place for the DataSet, otherwise it wouldn't be a core component in the .NET Framework. However, it is my contention that rarely, if ever, is the time and place for a DataSet in a Web application. In my experience, DataSets are useful in one of the two following situations:

  1. In a desktop, WinForms application. Consider a desktop-based data entry-type program. A user might fire up the program, load up the sales data from some database server, make some changes, and then want to save those changes. This is an ideal situation for the DataSet. It allows the data to be read into a DataSet residing in the client's memory, which affords the user the ability to work on the data without needing to constantly make trips back to the database. Upon completing editing the data, they can do a batch update, gracefully handling any changes that may have occurred while the user was working with the data in a disconnected state. Furthermore, since the DataSet is a disconnected data store, this data can be taken offline. A salesman traveling to a client's site could load this data and be able to review the data on his laptop while in transit, or while at the client's office.

    (A situation like this might arise in a Web application. I've worked on projects before where the client was adamant that they be able to interact with the Web application as discussed above. That is, they'd be able to visit a page, make a series of changes, and then click a single "Update" button. The underlying database data wouldn't be updated until that "Update" button was clicked. For this particular problem I used a Session-based DataSet, using the same techniques for a DataSet used in a desktop application for batch editing and updating.)

  2. For sending/receiving remote database information or for allowing communication between disparate platforms. Since a DataSet can be serialized/deserialized into XML so easily, they are a prime candidate for sending information across physical boundaries or as a means of serializing data into a platform-neutral format. For example, if you want to return database data from a Web service, one option is to simply read the database data into a DataSet and then return the DataSet from the Web service method. The DataSet will automatically be serialized into XML and sent over the wire. (Personally I don't recommend returning data from a Web service in this manner. Rather, I prefer to use custom business objects - it allows a finer degree of control over the XML serialization, provides a much lighter return payload, and appears less architecture-specific.)
Now, how often are you doing either of these things in your day-to-day ASP.NET development? Hardly ever, I'd wager, which is why you probably shouldn't be using DataSets! While the ASP.NET data Web controls are rather indifferent on what data object you use, you are suffering from a performance loss by choosing to use a DataSet.

Reasons Why You May Be Using a DataSet... and Reasons Why You Probably Shouldn't
In this article I have made a pretty blanket statement in saying, "Use DataReaders in Web applications and don't use DataSets." There are some scenarios in Web applications where it may seem like a DataSet is the only option. For example, imagine that you want to cache some database information that will be used on many pages across the site. This data may be user-specific and stored in the Session, or it may be the same across all users and therefore stored in the data cache. Regardless, a DataReader can't be cached because it is a connected data object, and connections to a database should be short-lived. That is, the absolutely last thing we want is an open connection sitting around in the cache. Therefore, if you want to have cached database data it may seem that the only option is to use a DataSet.

But it isn't the only option. You could, instead, create a class that has as its properties the database fields that you are storing in the DataSet. Then, when you wanted to cache the data, you could use a DataReader to read the query from the database and iterate through the records returned. For each record you'd create an instance of the custom class, set its properties to the field values of the query, and add the custom class to an ArrayList (or, preferably, a strongly-typed collection object). You'd then cache this collection of custom objects. Not only does this method prove more efficient, but, personally, I think it's more maintainable, as it removes the tight coupling between the database field names and accessing their values from the cached object (as with the DataSet). Furthermore, you can bind this custom collection to an ASP.NET data Web control exactly like you would a DataSet or DataReader. (See Displaying Custom Classes in a DataGrid for more information on this technique.)

Another reason you might use a DataSet is because you want to have random access to some data in order to search through the records, because these records may be used repeatedly. For example, when displaying a master/detail DataGrid where one column of a DataGrid contains the parent record and the other column contains another DataGrid with that particular row's children, it might make sense to use a DataSet to grab all of the children records from the database rather than having to requery the database for each DataGrid row's related set of children. (See An Extensive Examination of the DataGrid Web Control: Part 14 for more information on this technique. Essentially, it involves creating a DataGrid that looks similar to the one shown to the right.) The performance tradeoff here depends on how many rows are in the parent table. Since a DataSet is, roughly, 30 times slower than a DataReader, if there are more than 30 records in the parent table being displayed it probably makes sense to use a single DataSet rather than requerying for each parent record. (Ideally, a collection of custom objects would be used, as discussed earlier.)

Conclusion
In this article we examined the fundamentals of the two data access objects provided by ADO.NET: the DataReader and the DataSet. Both objects have their time and place in .NET applications but, in my opinion, DataSets are rarely, if ever, useful in ASP.NET Web applications. There are exceptions, granted, but for the majority of Web applications, DataReaders should be used exclusively.


Article written by Scott Mitchell (avaliable Here)

ASP.NET: DataSet vs DataReader (Pt. 01/03)

Tenho estado a trabalhar em ASP.NET e uma das grandes questões que surgiram tem a haver com a exportação dos dados da Base de Dados (SQL Server) para a aplicação C#/VB.NET.

Numa primeira tentativa, experimentei o DataSet como arquitectura para gestão do banco de dados e revelou-se um objecto poderoso, com imensas propriedades, imensos pormenores. Um DataSet acaba por ser um conjunto de tabelas da BD, onde são guardadas todas as linhas devolvidas pela instrução SQL. Estes dados são então tratados offline, ou seja, os dados podem ser alterados no dataset e não interfere com os dados existentes no banco de dados. Isto é muito útil para a manipulação de dados, controlo de cache, entre outras situações.

No entanto, depressa cheguei à conclusão que isto consumia muitos recursos, tanto é que o DataSet tem imensa informação desnecessária. Tive a ver e o payload do DataSet é simplesmente enorme.

Procurei uma solução. DataReader surgiu como a alternativa. Ora qual a diferença entre o DataReader e o DataSet? Primeiro que tudo, o DataReader trata os dados online, ao contrário do DataSet. Este objecto funciona como stream para o banco de dados e deve ser fechado depois de executados os comandos pretendidos. Esta é uma solução muito mais viável a nível de recursos, visto que consome muito, mas muito menos que o DataSet. Desvantagem? A flexibilidade é a grande desvantagem. Ao contrário do DataSet em que se pode manipular os dados directamente, o DataReader funciona como forward-only, ou seja, funciona como um array de dados que só pode estar a apontar para uma linha apenas, e só num sentido.


What is a DataReader?
A DataReader is a read-only stream of data returned from the database as the query executes. It only contains one row of data in memory at a time and is restricted to navigating forward only in the results one record at a time. The DataReader does support access to multiple result sets, but only one at a time and in the order retrieved. Just as in the original version of ADO, the data is no longer available through the DataReader once the connection to the data source is closed, which means a DataReader requires a connection to the database throughout its usage. Output parameters or return values are only available through the DataReader once the connection is closed.

What is a DataSet?
DataSet is the core of the ADO.NET disconnected architecture and is used to store data in a disconnected state..



Basicamente, estamos a falar dum cenário assim:

  • Data Reader - Forward only where as Dataset - Can loop through datas
  • Data Reader - Connected Recordset where as DataSet - Disconnected Recordset
  • Data Reader - Less Memory Occupying where as DataSet - It occupies more memory
  • Data Reader - Only Single Table can be used where as Dataset - Datatable Concept allows data to be stored in multiple tables.
  • Data Reader - Read only where as DataSet - Can add/update/delete using the dataset
  • Data Reader - No relationship can be maintained where as DataSet - Relationship can be maintained.
  • Data Reader - No Xml Storage available where as DataSet - Can be stored as XML.

De seguida, mostro um excelente artigo de Scott Mitchell, um dos fundadores do 4GuysFromRolla.