Sei sulla pagina 1di 11

ADO.

NET Architecture
The two main components of ADO.NET 3.0 for accessing and manipulating data are the .NET Framework data providers and the DataSet.

.NET Framework Data Providers


1. 2. 3. 4. 5. 6. The .NET Framework Data Providers are components that have been explicitly designed for data manipulation and fast, forward-only, read-only access to data. TheConnection object provides connectivity to a data source. The Command object enables access to database commands to return data, modify data, run stored procedures, and send or retrieve parameter information. The DataReader provides a high-performance stream of data from the data source. The DataAdapter provides the bridge between the DataSet object and the data source. The DataAdapter uses Command objects to execute SQL commands at the data source to both load the DataSet with data and synchronise changes that were made to the data in the DataSet back to the data source.

The DataSet
The ADO.NET DataSet is explicitly designed for data access independent of any data source. As a result, it can be used with multiple and differing data sources, used with XML data, or used to manage data local to the application. The DataSet contains a collection of one or more DataTable objects consisting of rows & columns of data, and also primary key, foreign key, constraint, and relation information about the data in the DataTable objects. For more information, seeDataSets, DataTables, and DataViews. The following diagram illustrates the relationship between a .NET Framework data provider and a DataSet.

Choosing a DataReader or a DataSet


When you decide whether your application should use a DataReader (see Retrieving Data Using a DataReader) or a DataSet (see DataSets, DataTables, and DataViews), consider the type of functionality that your application requires. Use a DataSet to do the following: Cache data locally in your application so that you can manipulate it. If you only need to read the results of a query, the DataReader is the better choice. Remote data between tiers or from an XML Web service. Interact with data dynamically such as binding to a Windows Forms control or combining and relating data from multiple sources. Perform extensive processing on data without requiring an open connection to the data source, which frees the connection to be used by other clients. If you do not require the functionality provided by the DataSet, you can improve the performance of your application by using the DataReader to return your data in a forward-only, read-only manner. Although the DataAdapter uses the DataReader to fill the contents of a DataSet (see Populating a DataSet from a DataAdapter), by using the DataReader, you can boost performance because you will save memory that would be consumed by the DataSet, and avoid the processing that is required to create and fill the contents of the DataSet.

Creating a DataSet
Describes the syntax for creating an instance of a DataSet. >You create an instance of a DataSet by calling the DataSet constructor. Optionally specify a name argument. If you do not specify a name for the DataSet, the name is set to "NewDataSet". >You can create a new DataSet based on an existing DataSet. >The new DataSet can be an exact copy of the existing DataSet; a clone of the DataSet that copies the relational structure or schema but that does not contain any of the data from the existing DataSet; >It can be a subset of the DataSet, containing only the modified rows from the existing DataSet using the GetChanges method. For more information, see Copying DataSet Contents. DataSet customerOrders = new DataSet("CustomerOrders");

Adding a DataTable to a DataSet


ADO.NET enables you to create DataTable objects and add them to an existing DataSet. You can set constraint informa tion for a DataTable by using thePrimaryKey and Unique properties. The following example constructs a DataSet, adds a new DataTable object to the DataSet, and then adds three DataColumn objects to the table. Finally, the code sets one column as the primary key column. DataSet customerOrders = new DataSet("CustomerOrders"); DataTable ordersTable = customerOrders.Tables.Add("Orders"); DataColumn pkOrderID = ordersTable.Columns.Add("OrderID", typeof(Int32)); ordersTable.Columns.Add("OrderQuantity", typeof(Int32)); ordersTable.Columns.Add("CompanyName", typeof(string)); ordersTable.PrimaryKey = new DataColumn[] { pkOrderID };

Case Sensitivity
Two or more tables or relations with the same name, but different casing, can exist in a DataSet. In such cases, references by name to tables and relations are case sensitive. For example, if the DataSet dataSet contains tables Table1 and table1, you would reference Table1 by name as dataSet.Tables["Table1"], and table1as dataSet.Tables["table1"]. Attempting to reference either of the tables as dataSet.Tables["TABLE1"] would generate an exception. The case-sensitivity behavior does not apply if only one table or relation has a particular name. For example, if the DataSet has only Table1, you can reference it using dataSet.Tables["TABLE1"].

The CaseSensitive property of the DataSet does not affect this behavior. The CaseSensitive property applies to the data in the DataSet and affects sorting, searching, filtering, enforcing constraints, and so on.

Namespace Support
In versions of ADO.NET earlier than 2.0, two tables could not have the same name, even if they were in different namespaces. This limitation was removed in ADO.NET 2.0. A DataSet can contain two tables that have the same TableName property value but different Namespace property values.

Adding DataRelations
Describes how to create relations between tables in a DataSet. In a DataSet with multiple DataTable objects, you can use DataRelation objects to relate one table to another, to navigate through the tables, and to return child or parent rows from a related table. The arguments required to create a DataRelation are a name for the DataRelation being created, and an array of one or more DataColumn references to the columns that serve as the parent and child columns in the relationship. After you have created a DataRelation, you can use it to navigate between tables and to retrieve values. Adding a DataRelation to a DataSet adds, by default, a UniqueConstraint to the parent table and a ForeignKeyConstraint to the child table. For more information about these default constraints, see DataTable Constraints. The following code example creates a DataRelation using two DataTable objects in a DataSet. Each DataTable contains a column named CustID, which serves as a link between the two DataTable objects. The example adds a single DataRelation to the Relations collection of the DataSet. The first argument in the example specifies the name of the DataRelation being created. The second argument sets the parent DataColumn and the third argument sets the child DataColumn. customerOrders.Relations.Add("CustOrders", customerOrders.Tables["Customers"].Columns["CustID"] , customerOrders.Tables["Orders"].Columns["CustID"]); A DataRelation also has a Nested property which, when set to true, causes the rows from the child table to be nested within the associated row from the parent table when written as XML elements using WriteXml . For more information, see Using XML in a DataSet.

(B)What is difference between dataset and datareader ?


Following are some major differences between dataset and datareader : DataReader provides forward-only and read-only access to data, while the DataSet object can hold more than one table (in other words more than one rowset) from the same data source as well as the relationships between them. Dataset is a disconnected architecture while datareader is connected architecture. Dataset can persist contents while datareader can not persist contents, they are forward only. (B) What is the difference between DataSet and DataReader ? Twist :- Why is DataSet slower than DataReader ? Fourth point is the answer to the twist. Note:- This is my best question and I expect everyone to answer it. It is asked almost 99% in all companies....Basic very Basic cram it. Following are the major differences between DataSet and DataReader : DataSet is a disconnected architecture, while DataReader has live connection while reading data. If we want to cache data and pass to a different tier DataSet forms the best choice and it has decent XML support. When application needs to access data from more than one table DataSet forms the best choice. If we need to move back while reading records, datareader does not support this functionality. But one of the biggest drawbacks of DataSet is speed. As DataSet carry considerable overhead because of relations, multiple tables etc speed is slower than DataReader. Always try to use DataReader wherever possible, as its meant specially for speed performance.

(B)What is Dataset object?


The DataSet provides the basis for disconnected storage and manipulation of relational data. We fill it from a data store,work with it while disconnected from that data store, then reconnect and flush changes back to the data store if required. (B)What are the various objects in Dataset ? Dataset has a collection of DataTable object within the Tables collection. Each DataTable object contains a collection of DataRow objects and a collection of DataColumn objects. There are also collections for the primary keys, constraints, and default values used in this table which is called as constraint collection, and the parent and child relationships between the tables. Finally, there is a DefaultView object for each table. This is used to create a DataView object based on the table, so that the data can be searched, filtered or otherwise manipulated while displaying the data.

(B) How can we force the connection object to close after my datareader is closed ?
Command method Executereader takes a parameter called as CommandBehavior where in we can specify saying close connection automatically after the Datareader is close. pobjDataReader = pobjCommand.ExecuteReader(CommandBehavior.CloseConnection)

(B) I want to force the datareader to return only schema of the datastore rather than data ?
pobjDataReader = pobjCommand.ExecuteReader(CommandBehavior.SchemaOnly)

(B) What are the steps involved to fill a dataset ? Twist :- How can we use dataadapter to fill a dataset ?
Sample code is provided in WindowsDataSetSample folder in CD.LoadData has all the implementation of connecting and loading to dataset. This dataset is finally bind to a ListBox. Below is the sample code.
Private Sub LoadData() Dim strConnectionString As String strConnectionString = AppSettings.Item(ConnectionString) Dim objConn As New SqlConnection(strConnectionString) objConn.Open() Dim objCommand As New SqlCommand(Select FirstName from Employees) objCommand.Connection = objConn Dim objDataAdapter As New SqlDataAdapter() objDataAdapter.SelectCommand = objCommand Dim objDataSet As New DataSet End Sub

In such type of questions interviewer is looking from practical angle, that have you worked with dataset and datadapters. Let me try to explain the above code first and then we move to what steps should be told during interview. Dim objConn As New SqlConnection(strConnectionString) objConn.Open() First step is to open the connection.Again note the connection string is loaded from config file. Dim objCommand As New SqlCommand(Select FirstName from Employees) objCommand.Connection = objConn Second step is to create a command object with appropriate SQL and set the connection object to this command. Dim objDataAdapter As New SqlDataAdapter() objDataAdapter.SelectCommand = objCommand Third steps is to create the Adapter object and pass the command object to the adapter object. objDataAdapter.Fill(objDataSet) Fourth step is to load the dataset using the Fill method of the dataadapter. lstData.DataSource = objDataSet.Tables(0).DefaultView lstData.DisplayMember = FirstName lstData.ValueMember = FirstName Fifth step is to bind to the loaded dataset with the GUI. At this moment sample has listbox as the UI. Binding of the UI is done by using DefaultView of the dataset. Just to revise every dataset has tables and every table has views. In this sample we have only loaded one table i.e. Employees table so we are referring that with an index of zero. Just say all the five steps during interview and you will see the smile on the interviewers face and appointment letter in your hand. (B)What are the various methods provided by the dataset object to generate XML? Note:XML is one of the most important leap between classic ADO and ADO.NET. So this question is normally asked more generally how can we convert any data to XML format. Best answer is convert in to dataset and use the below methods. ReadXML Reads a XML document in to Dataset. GetXML This is a function which returns the string containing XML document. WriteXML This writes a XML data to disk.

(B) How can we save all data from dataset ?


Dataset has AcceptChanges method which commits all the changes since last time Acceptchanges has been executed. Note :- This book does not have any sample of Acceptchanges. I leave that to readers as homework sample. But yes from interview aspect that will be enough.

(B) How can we check that some changes have been made to dataset since it was loaded ? Twist :- How can we cancel all changes done in dataset ? Twist :- How do we get values which are changed in a dataset ? For
tracking down changes Dataset has two methods which comes as rescue GetChanges and HasChanges. GetChanges Returns dataset which are changed since it was loaded or since Acceptchanges was executed. HasChanges This property indicates that has any changes been made since the dataset was loaded or acceptchanges method was executed. If we want to revert or abandon all changes since the dataset was loaded use RejectChanges. Note:- One of the most misunderstood things about these properties is that it tracks the changes of actual database. That is a fundamental mistake; actually the changes are related to only changes with dataset and have nothing to with changes happening in actual database. As dataset are disconnected and do not know anything about the changes happening in actual database.

(B) How can we add/remove rows in DataTable object of DataSet ?


Datatable provides NewRow method to add new row to DataTable. DataTable has DataRowCollection object which has all rows in a DataTable object. Following are the methods provided by DataRowCollection object :- Add Adds a new row in DataTable Remove It removes a DataRow object from DataTable RemoveAt It removes a DataRow object from DataTable depending on index position of the DataTable.

(B) How can we load multiple tables in a DataSet ?


objCommand.CommandText = "Table1" objDataAdapter.Fill(objDataSet, "Table1") objCommand.CommandText = "Table2" objDataAdapter.Fill(objDataSet, "Table2") Above is a sample code which shows how to load multiple DataTable objects in one DataSet object. Sample code shows two tables Table1 and Table2 in object ObjDataSet. lstdata.DataSource = objDataSet.Tables("Table1").DefaultView In order to refer Table1 DataTable, use Tables collection of DataSet and the Defaultview object will give you the necessary output. (B) How can we add relations between table in a DataSet ? Dim objRelation As DataRelation objRelation=New DataRelation("CustomerAddresses",objDataSet.Tables("Customer").Columns("Custid") ,objDataSet.Tables("Addresses").Columns("Custid_fk")) objDataSet.Relations.Add(objRelation) Relations can be added between DataTable objects using the DataRelation object. Above sample code is trying to build a relationship between Customer and Addresses Datatable using CustomerAddresses DataRelation object. (I)What is difference between Dataset. clone and Dataset. copy ? Clone: - It only copies structure, does not copy data. Copy: - Copies both structure and data.

Retrieving Data Using a DataReader (ADO.NET)


Visual Studio 2008 Retrieving data using a DataReader involves creating an instance of the Command object and then creating a DataReader by calling Command.ExecuteReader to retrieve rows from a data source. The following example illustrates using a DataReader where reader represents a valid DataReader and command represents a valid Command object. reader = command.ExecuteReader(); You use the Read method of the DataReader object to obtain a row from the results of the query. You can access each column of the returned row by passing the name or ordinal reference of the column to the DataReader. However, for best performance, the DataReader provides a series of methods that allow you to access column values in their native data types (GetDateTime, GetDouble, GetGuid, GetInt32, and so on). For a list of typed accessor methods for data provider-specific DataReaders, see OleDbDataReader and SqlDataReader. Using the typed accessor methods, assuming the underlying data type is known, reduces the amount of type conversion required when retrieving the column value.

The Windows Server 2003 release of the .NET Framework includes an additional property for the DataReader, HasRows, which enables you to determine if theDataReader has returned any results before reading from it.
The following code example iterates through a DataReader object, and returns two columns from each row. C# Example static void HasRows(SqlConnection connection) { using (connection) { SqlCommand command = new SqlCommand( "SELECT CategoryID, CategoryName FROM Categories;", connection); connection.Open(); SqlDataReader reader = command.ExecuteReader(); if (reader.HasRows) { while (reader.Read()) { Console.WriteLine("{0}\t{1}", reader.GetInt32(0), reader.GetString(1)); } } else { Console.WriteLine("No rows found."); } reader.Close(); } }

The DataReader provides an unbuffered stream of data that allows procedural logic to efficiently process results from a data source sequentially. The DataReaderis a good choice when retrieving large amounts of data because the data is not cached in memory.

Closing the DataReader


You should always call the Close method when you have finished using the DataReader object. If your Command contains output parameters or return values, they will not be available until the DataReader is closed. Note that while a DataReader is open, the Connection is in use exclusively by that DataReader. You cannot execute any commands for the Connection, including creating another DataReader, until the original DataReader is closed.

Do not call Close or Dispose on a Connection, a DataReader, or any other managed object in the Finalize method of your class. In a finalizer, only release unmanaged resources that your class owns directly. If your class does not own any unmanaged resources, do not include a Finalize method in your class definition. For more information, see Garbage Collection.

Retrieving Multiple Result Sets using NextResult


If multiple result sets are returned, the DataReader provides the NextResult method to iterate through the result sets in order. The following example shows theSqlDataReader processing the results of two SELECT statements using the ExecuteReader method. C# Example static void RetrieveMultipleResults(SqlConnection connection) { using (connection) { SqlCommand command = new SqlCommand( "SELECT CategoryID, CategoryName FROM dbo.Categories;" + "SELECT EmployeeID, LastName FROM dbo.Employees", connection); connection.Open(); SqlDataReader reader = command.ExecuteReader(); while (reader.HasRows) { Console.WriteLine("\t{0}\t{1}", reader.GetName(0), reader.GetName(1)); while (reader.Read()) { Console.WriteLine("\t{0}\t{1}", reader.GetInt32(0), reader.GetString(1)); } reader.NextResult(); } } }

Getting Schema Information from the DataReader


While a DataReader is open, you can retrieve schema information about the current result set using the GetSchemaTable method. GetSchemaTable returns aDataTable object populated with rows and columns that contain the schema information for the current result set. The DataTable contains one row for each column of the result set. Each column of the schema table row maps to a property of the column returned in the result set, where the ColumnName is the name of the property and the value of the column is the value of the property. The following code example writes out the schema information for DataReader. C# Example static void GetSchemaInfo(SqlConnection connection) { using (connection) { SqlCommand command = new SqlCommand( "SELECT CategoryID, CategoryName FROM Categories;", connection); connection.Open(); SqlDataReader reader = command.ExecuteReader(); DataTable schemaTable = reader.GetSchemaTable(); foreach (DataRow row in schemaTable.Rows) { foreach (DataColumn column in schemaTable.Columns) { Console.WriteLine(String.Format("{0} = {1}", column.ColumnName, row[column])); } } } }

The SelectCommand property of the DataAdapter is a Command object that retrieves data from the data source. The InsertCommand, UpdateCommand, andDeleteCommand properties of the DataAdapter are Command objects that manage updates to the data in the data source according to modifications made to the data in the DataSet. The Fill method of the DataAdapter is used to populate a DataSet with the results of the SelectCommand of the DataAdapter. Fill takes as its arguments a DataSet to be populated, and a DataTable object, or the name of the DataTable to be filled with the rows returned from the SelectCommand. The Fill method uses the DataReader object implicitly to return the column names and types that are used to create the tables in the DataSet, and the data to populate the rows of the tables in the DataSet. // Assumes that connection is a valid SqlConnection object. string queryString = "SELECT CustomerID, CompanyName FROM dbo.Customers"; SqlDataAdapter adapter = new SqlDataAdapter(queryString, connection); DataSet customersDS = new DataSet(); adapter.Fill(customersDS, "Customers"); //Fill(DataSet,DataTable)

Multiple Result Sets


If the DataAdapter encounters multiple result sets, it creates multiple tables in the DataSet. The tables are given an incremental default name of TableN, starting with "Table" for Table0. If a table name is passed as an argument to the Fill method, the tables are given an incremental default name of TableNameN, starting with "TableName" for TableName0. // Assumes that customerConnection is a valid SqlConnection object. // Assumes that orderConnection is a valid OleDbConnection object. SqlDataAdapter custAdapter = new SqlDataAdapter( "SELECT * FROM dbo.Customers", customerConnection); OleDbDataAdapter ordAdapter = new OleDbDataAdapter( "SELECT * FROM Orders", orderConnection); DataSet customerOrders = new DataSet(); custAdapter.Fill(customerOrders, "Customers"); ordAdapter.Fill(customerOrders, "Orders"); DataRelation relation = customerOrders.Relations.Add("CustOrders", customerOrders.Tables["Customers"].Columns["CustomerID"], customerOrders.Tables["Orders"].Columns["CustomerID"]); foreach (DataRow pRow in customerOrders.Tables["Customers"].Rows) { Console.WriteLine(pRow["CustomerID"]); foreach (DataRow cRow in pRow.GetChildRows(relation)) Console.WriteLine("\t" + cRow["OrderID"]); }

10

Updating Data Sources with DataAdapters


The Update method of the DataAdapter is called to resolve changes from a DataSet back to the data source. The Update method, like the Fill method, takes as arguments an instance of a DataSet, and an optional DataTable object or DataTable name. The DataSet instance is the DataSet that contains the changes that have been made, and the DataTable identifies the table from which to retrieve the changes. If no DataTable is specified, the first DataTable in the DataSet is used. When you call the Update method, the DataAdapter analyzes the changes that have been made and executes the appropriate command (INSERT, UPDATE, or DELETE). When the DataAdapter encounters a change to a DataRow, it uses the InsertCommand, UpdateCommand, or DeleteCommand to process the change. This allows you to maximize the performance of your ADO.NET application by specifying command syntax at design time and, where possible, through the use of stored procedures. You must explicitly set the commands before calling Update. If Update is called and the appropriate command does not exist for a particular update (for example, no DeleteCommand for deleted rows), an exception is thrown.

private static void AdapterUpdate(string connectionString) { using (SqlConnection connection = new SqlConnection(connectionString)) { SqlDataAdapter dataAdpater = new SqlDataAdapter( "SELECT CategoryID, CategoryName FROM Categories", connection); dataAdpater.UpdateCommand = new SqlCommand( "UPDATE Categories SET CategoryName = @CategoryName " + "WHERE CategoryID = @CategoryID", connection); dataAdpater.UpdateCommand.Parameters.Add( "@CategoryName", SqlDbType.NVarChar, 15, "CategoryName"); SqlParameter parameter = dataAdpater.UpdateCommand.Parameters.Add( "@CategoryID", SqlDbType.Int); parameter.SourceColumn = "CategoryID"; parameter.SourceVersion = DataRowVersion.Original; DataTable categoryTable = new DataTable(); dataAdpater.Fill(categoryTable); DataRow categoryRow = categoryTable.Rows[0]; categoryRow["CategoryName"] = "New Beverages"; dataAdpater.Update(categoryTable); Console.WriteLine("Rows after update."); foreach (DataRow row in categoryTable.Rows) { { Console.WriteLine("{0}: {1}", row[0], row[1]); } } } }

11

Potrebbero piacerti anche