Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
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.
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.
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");
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) 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 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.
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.
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.
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)
10
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