Friday, August 17, 2007

Policy Injection Application Block

Introduction

The purpose of the Policy Injection Application Block is to separate the core concerns and crosscutting concerns.

A policy is a collection of matching rules that specifies how the Plolicy Injection Application Block selects classes and members to which it will attach a handler pipeline and a collection of the handlers that make up that pipeline.

A policy is not limited to a single class or a class member; depending on the matching rules, it can apply to all the members of one class, all the members of several classes, some members of one class, some members of multiple classes or some other combination.


Using the Create Method

1. It creates an instance of the target class.
2. It creates suitable proxy for the class or for the specified interface that the class implements.
3. It wires up the specified handlers into a pipeline between the relevant methods and properties of the proxy and the concreate target class instance.
4. It returns a reference to the proxy.

The Policy Injection Application Block addresses the following scenarios

-building applications from objects
-managing cross-cutting concerns
-allowing the developer and administrator to configure the behavior of objects

Design goals
- allow policies to be dynamically applied to any business objects
- allow policies to be modified without changing the code
- minimize the performance impact of checking for and applying policies at run time
- provides extensibility of handlers, matching rules, and interception mechanism
- allow developers to create and reuse key parts of the infrastructure independently

Scenarios for Using the Policy Injection Application Block
1. Logging Method Invocation and Property Access
allow developers and administrators to oconfigure logging to the Windows Event Log, e-mail messages, databases, message queue systems, text files, WMI events, or custom locations.
2. Handling Exceptions in a Structured Manner.
They include
Logging exception information
Hiding sensitive information by replacing the original exception with another exception
3. Validating Parameter Value
this minimizes the code developers have to create and it allows administrators to modify the validation policies through configuration, if required
4. Caching Method Results and Property Values
if the application repeatedly calls methods during its execuotion, the caching can reduce the demands the application places on hardware and system resources and increase perceived response times.
The Caching Handler is also useful for caching the values of properties exposed by classes
5. Authorizing Method and Property Requests
The Policy Injection Application Block provides a handler that will check the authorization status of the requesting user or thread against the target class permissions before calling the target method or accessing the target property.
6. Measuring Target method Performance
The Policy Injection Application Block contains instrumentation that allows developers, administrators, and operators to monitor the performance of the application block itself.


How to incorporate the Policy Injection Application Block
1. Add reference
Microsoft.Practices.EnterpriseLibrary.PolicyInjection.dll
Microsoft.Practices.EnterpriseLibrary.Common.dll
Microsoft.Practices.EnterpriseLibrary.ObjectBuilder.dll

Using Microsoft.Practices.EnterpriseLibrary.PolicyInjection

2. Reordering Policies
If more than one policy matches a specified method, the application block will apply the policies in the order they occur in the configuration. It is possible to change the order of policies defined for the Policy Inojection Application Block.
Right-click the policy node you want to move, and then click either Move Up or Move Down.

3. Defining and Configuring Handler Pipelines.
The Handlers section of a policy defines the series of handlers that the Policy Injection Application Block will execute when client node calls a method or sets a property of the target class that corresponds to the matching rules defined for that policy
The Application Block executes the pre-processing task of each handler in the order that they occur in configuration.
The Application Block then calls the specified method
The Application Block then executes the post-processing task of each handler.

Key Scenarios and Development Tasks

1. Deciding if an Object is Interceptable
2. Objects that Derive From MarshalByRefObject
3. Objects that Implement a Known Interface
4. Creating and Wrapping Object Instances
5. Creating New Policy-Enabled Target Objects


built-in matching rules
1. The Assemply Maching Rule
allows developers, operators, and administrators to select target classes bases on the file name of the asssembly.
2. The Custom Attribute Matching Rule
allows to select target classes based on a custom attribute type that is appiled to class members.
3. The Member Name Matching Rule
allows to select target classes based on the name of the class members (methods or properties), including using wildcard characters for the member name.
4. The Method Signature Matching Rule
allows to select target classes based on the name and signature of its members.
5. The Namespace Matching Rule
allows to select target classes based on their namespace, using wildcard characters for the child namespace names but not for the root namespace name.
6. The Parameter Type Mathing Rule
allows to select target classes based on the type name of a parameter for a member of the target object.
7. The property Matching Rule
allows to select individual properties of the target classes based on their name. including using wildcard characters, and the combination of accessors they include.
8. The Return Type matching Rule
allows to select classes based on the type name of the return value, using wildcard characters for the type name.
9. The Tag Attribute Matching Rule
allows to select target classes based on the name of an attribute of type Tag that is applied to a class, or to members within a class, including using wildcard characters for the attribute name.
10. The Type Mactching Rule
allows to select target classes using the namespace and class names.
11. Custom Matching Rules
Developers can create custom matching rules that integrate with the Policy Injection Application Block.

Built-in handlers
1. The Authosization Handler
provides the capability to check that the current user has the requisite permission to access the selected object method or property. This handler uses the Security Apllication Block and takes advantage of the features that it exposes.
2. The Caching Handler
provides the capability to cache the value or object instance returned from the selected method or the value of the selected property. This handler using the Caching Appication Block. The Caching Hadler applies both beforeand after invocation of the selected method or setting of the selected property of the target object.
3. The Exception Handling Handler
provides the capability to manage and process exceptions in a standard way. This handler uses the Exception Handling Application Block. The Exception Handling Handler applies after invocation of the selected method or access to the selected propery of the target object.
4. The Logging Handler
The Logging Handler provides the capability to write log mesages and trae messages as the client code invokes the selected method or accesses the selected property of the target object. This handler uses the Logging Application Block. The logging Handler applies both before and after invoking the selected method.
5. The Performance Counter Handler
increments a specific counter each time it executes in response to invocation of the selected method or setting of the selected property. This handler uses the instrumentation features that are part of the Enterprise Library Core. THe Performance Counter Handler applies both before and after invocation of the selected method or access to the selected property of the target object.
6. The Validation Handler
The Validation Handler provides the capability to test whether the value provided for the selected property, or the values specified for the parameters of the selected method, are valid against rules. This handler uses the Validation Application Block. The Validation Handler applies the validation before invoking the method or setting the property of the target object.
7. The custom Pipeline Handler
Developers can create custom handlers that integrate with the Policy Injection Application Block.


Effective Policy Viewer
Is a tool that can analyze an assembly using a specified configuration file and discover the actual handler policy that will apply to the classes within the assembly.

Thursday, August 16, 2007

Data Access Application Block

Introduction

Each database has its connection information stored in a configuration file. It reduces difficulty in changing the database type.
1. Create the database object.
2. Suppy the parameters for the command, if they are needed.
3. Call the appropriate method(s). These methods are optimized for performance. They are also portable.

Data Access Application Block Dependencies
-Core library functionality - Microsoft.Practices.EnterpriseLibrary.Common.dll
-The ObjectBulder subsystem - Microsoft.Practices.ObjectBuilder - performs all the repetitive and necessary tasks for creating and disposing object instances.

Developing Applications Using the Data Access Application Block


Entering Configuration Information

To add the Data Access Application Block
1. Open the configuration file.
2. Right-click Application configuration, New, Data Access Application Block.

To configure the default database
3. expand DefaultDatabse property.
4. Enter a connection string name.
5. Change the provider name if you want to.

Adding Application Code
1. add reference
Microsoft.Practices.EnterpriseLibrary.Data.dll
Microsoft.Practices.EnterpriseLibrary.Common.dll

2. In source code,
Using Microsoft.Practices.EnterpriseLibrary.Data

3. Creating a Database Object
Dim db As Database = DatabaseFactory.CreateDatabase()
SqlDatabase, OracleDatabase, SqlCeDatabase are specific to a particular database type. They can be used instead of Database

Creating a Dbcommand Object

DbCommand objects are separated into two types
1. GetStoredProcCommand. This method is for stored procedures commands.
2. GetSqlStringCommand. This method is for SQL text commands.

example
for GetStoredProcCommand.
Dim db As Database = DatabaseFactory.CreateDatabase()
Dim sqlCommand As String = "Select CustomerID, LastName, FirstName From Customers"
Dim dbCommand As DbCommand = db.GetSqlStringCommand(sqlCommand)

for GetSqlStringCommand.
Dim db As Database = DatabaseFactory.CreateDatabase()
Dim dbCommand As DbCommand
dbCommand = db.GetStoredProcCommand("GetProductsByCategory")

TransactionScope Class
It assumes that you will use a single connection for all the database calls that occur within the transaction.

Handling Parameters
Attributes can include direction, data types, and length.
The Database class includes a variety of methods for passing parameters to stored procedures.
1. AddParameter- this method passes a parameter (input or output) to a stored procedure.
2. AddInParameter - This method passes an input parameter to a stored procedure.
3. AddOutParameter - This method adds an output parameter.
4. GetparameterValue - This method finds the value of the specified parameter.
5. SetParameterValue - This method sets the value of the specified parameter.


Dim db As Database = DatabaseFactory.CreateDatabase()
Dim sqlCommand As String = "GetProductDetails"
Dim dbCommand As DbCommand = db.GetStoredProcCommand(sqlCommand)

db.AddInParameter(dbCommand, "ProductID", DbType.Int32, 5)
db.AddOutParameter(dbCommand, "ProductName", DbType.String, 50)
db.AddOutParameter(dbCommand, "UnitPrice", DbType.Currency, 8)


Using a DbDataReader to Retrieve Multiple Rows

Used to retrieve data for read-only purposes, which in most cases means that you want to display the data.
The Database class implementation of ExecuteReader returns a DbDataReader object. The DbDataReader supports data binding and can act as a data source for a number of ASP.NET server controls.

Using ExecuteDataReader

Dim db As Database = DatabaseFactory.CreateDatabase()

Using dataReader As IDataReader = db.ExecuteReader(CommandType.Text, "Select Name, Address, City From Customers")

customerGrid.DataSource = dataReader
customerGrid.DataBind()

End Using

The ExecuteReader method opens a connection to the dtabase and uses the CommandBehavior.CloseConnection method to couple the lifetime of the connection to that of the reader. So closing the reader causes the connection to be closed and returned to the connection pool.


Using a DataSet to Retrieve Multiple rows

Retrieve multiple tables or tables from different data sources.
for exchange data with another application.
access interdependent records for data processing.

Using ExecuteDataSet


Dim db As Database = DatabaseFactory.CreateDatabase()

Dim sqlCommand As String = "GetProductsByCategory"
Dim dbCommand As DbCommand = db.GetStoredProcCommand(sqlCommand)

' Retrieve products from the category 7.
Dim category As Integer = 7
db.AddInParameter(dbCommand, "CategoryID", DbType.Int32, category)

' DataSet that will hold the returned results
Dim customerproductDataSet As DataSet = Nothing

customerproductDataSet = db.ExecuteDataSet(dbCommand)


If you want to reuse an existing DataSet instead of creating a new one to hold the results of your query, use the LoadDataSet method in the Database class.


Executing a Command and Accessing Output Parameters.

Retrieve specific items of data either from one row in a particular table or from multiple related rows in different tables.
Use a stored procedure's output parameters.

Using ExecuteNonQuery

Dim db As Database = DatabaseFactory.CreateDatabase()

Dim sqlCommand As String = "GetProductDetails"
Dim dbCommand As DbCommand = db.GetStoredProcCommand(sqlCommand)

db.AddInParameter(dbCommand, "ProductID", DbType.Int32, 3)
db.AddOutParameter(dbCommand, "ProductName", DbType.String, 50)
db.AddOutParameter(dbCommand, "UnitPrice", DbType.Currency, 8)

db.ExecuteNonQuery(dbCommand)

Dim results As String = String.Format(CultureInfo.CurrentCulture, "{0}, {1}, {2:C} ", _
db.GetParameterValue(dbCommand, "ProductID"), _
db.GetParameterValue(dbCommand, "ProductName"), _
db.GetParameterValue(dbCommand, "UnitPrice"))


Executing a Command and Accessing a Single-Item Result

The goal in this scenario is to return a single value as the result of a query.

Using ExecuteScalar

Dim db As Database = DatabaseFactory.CreateDatabase()

Dim sqlCommand As String = "GetProductName"
Dim productId As Integer = 7
Dim dbCommand As DbCommand = db.GetStoredProcCommand(sqlCommand, productId)

Dim productName As String = DirectCast(db.ExecuteScalar(dbCommand), String)



Performing Multiple Updates within a Transaction

Transactions ensure the integrity of a database system's state. When an application executes multiple operations against a database, a common requirement is that all of the operations must succeed or the database must roll back to its original state.

Using ExecuteNonQuery in a Transaction

Public Function Transfer(ByRef transactionAmount As Integer, ByRef sourceAccount As Integer, ByRef destinationAccount As Integer) As Boolean

Dim result As Boolean = False

' Create the database object, using the default database service. The
' default database service is determined through configuration.
Dim db As Database = DatabaseFactory.CreateDatabase()

' Two operations, one to credit an account, and one to debit another
' account.
Dim sqlCommand As String = "CreditAccount"
Dim creditCommand As DbCommand = db.GetStoredProcCommand(sqlCommand)

db.AddInParameter(creditCommand, "AccountID", DbType.Int32, sourceAccount)
db.AddInParameter(creditCommand, "Amount", DbType.Int32, transactionAmount)

sqlCommand = "DebitAccount"
Dim debitCommand As DbCommand = db.GetStoredProcCommand(sqlCommand)
db.AddInParameter(debitCommand, "AccountID", DbType.Int32, destinationAccount)
db.AddInParameter(debitCommand, "Amount", DbType.Int32, transactionAmount)

Using connection As DbConnection = db.CreateConnection()
connection.Open()
Dim transaction As DbTransaction = connection.BeginTransaction()

Try

' Credit the first account.
db.ExecuteNonQuery(creditCommand, transaction)
' Debit the second account.
db.ExecuteNonQuery(debitCommand, transaction)
' Commit the transaction.
transaction.Commit()

result = True
Catch
' Roll back the transaction.
transaction.Rollback()
End Try

connection.Close()
Return result
End Using
End Function

Using a DataSet to Update a Database


Using UpdateDataSet

Dim db As Database = DatabaseFactory.CreateDatabase()

Dim productsDataSet As DataSet = new DataSet()

Dim sqlCommand As String = "Select Select ProductID, ProductName, CategoryID, UnitPrice, LastUpdate From Products"
Dim dbCommand As DbCommand = db.GetSqlStringCommand(sqlCommand)

Dim productsTable As String = "Products"

' Retrieve the initial data.
db.LoadDataSet(dbCommand, productsDataSet, productsTable)

' Get the table that will be modified.
Dim table As DataTable = productsDataSet.Tables(productsTable)

' Add a new product to existing DataSet.
Dim addedRow As DataRow = table.Rows.Add(New Object() {DBNull.Value, "New product", 11, 25})

' Modify an existing product.
table.Rows(0)("ProductName") = "Modified product"

' Establish the Insert, Delete, and Update commands.
Dim insertCommand As DbCommand = db.GetStoredProcCommand("AddProduct")
db.AddInParameter(insertCommand, "ProductName", DbType.String, "ProductName", DataRowVersion.Current)
db.AddInParameter(insertCommand, "CategoryID", DbType.Int32, "CategoryID", DataRowVersion.Current)
db.AddInParameter(insertCommand, "UnitPrice", DbType.Currency, "UnitPrice", DataRowVersion.Current)

Dim deleteCommand As DbCommand = db.GetStoredProcCommand("DeleteProduct")
db.AddInParameter(deleteCommand, "@ProductID", DbType.Int32, "ProductID", DataRowVersion.Current)

Dim updateCommand As DbCommand = db.GetStoredProcCommand("UpdateProduct")
db.AddInParameter(updateCommand, "ProductID", DbType.Int32, "ProductID", DataRowVersion.Current)
db.AddInParameter(updateCommand, "ProductName", DbType.String, "ProductName", DataRowVersion.Current)
db.AddInParameter(updateCommand, "LastUpdate", DbType.DateTime, "LastUpdate", DataRowVersion.Current)

' Submit the DataSet, capturing the number of rows that were affected.
Dim rowsAffected As Integer = db.UpdateDataSet(productsDataSet, "Products", insertCommand, updateCommand, _
deleteCommand, Microsoft.Practices.EnterpriseLibrary.Data.UpdateBehavior.Standard)

The UpdateDataSet method can specify the behavior that should occur when it encounters an error.
1. Standard - If the Update command encounters an error, the updates stops. Additional rows in the Datatable are unaffected.
2. Continue - The update command will try to update the remaining rows.
3. Transactional - All updated rows will be rolled back.

Retriving Multiple Rows as XML


Using ExecuteXmlReader

Dim dbSQL As SqlDatabase = DirectCast(DatabaseFactory.CreateDatabase("EntLibQuickStartsSql"), SqlDatabase)

' Use "FOR XML AUTO" to have SQL return XML data.
Dim sqlCommand As String = "SELECT ProductID, ProductName FROM Products FOR XML AUTO"
Dim dbCommand As DbCommand = dbSQL.GetSqlStringCommand(sqlCommand)

Dim productsReader As XmlReader = Nothing
Dim productList As StringBuilder = New StringBuilder()

Try

productsReader = dbSQL.ExecuteXmlReader(dbCommand)

' Iterate through the XmlReader and put the data into our results.
While (Not productsReader.EOF)
If (productsReader.IsStartElement()) Then
productList.Append(productsReader.ReadOuterXml())
productList.Append(Environment.NewLine)
End If
End While

Finally
' Close the Reader if there is no active transaction.
If (Not productsReader Is Nothing And Transaction.Current Is Nothing) Then
productsReader.Close()
End If
End Try

The ExecuteXmlReader method of the SqlCommand object currently does not support the CommandBehavior.CloseConnection. So you must explicitly close the connection when you finish with the reader.