Design data layer components and deliver data between layers
Angela Crocker, Andy Olsen and Edward Jezierski
Microsoft Corporation
August 2002
Applicable to: Microsoft® .NET application
Summary: Learn the best way to disclose data to Microsoft .NET applications, and how to implement an effective policy to deliver data between the interlayer of the distributed application. (This article contains some links to English sites.)
table of Contents
Introduction to map relational data to business entity implementation of data access logic components to implement business entity transaction verification error management Authorization and security deployment appendix collaborators
Introduction
When designing a distributed application, you need to determine how to access and represent business data associated with the application. This article provides some guiding principles to help you select the best way to transfer data and maintain data between the application's interlayer.
Figure 1 shows a common layer in a distributed application. This document distinguishes business data and the business process using these data, and discusses the business process layer only when it is necessary to clearly explain. Also, this paper discusses the representation when directing the data representation (such as the way of the Microsoft® ASP.NET web page public service data). Two new terms are used in Figure 1: Data Access Logic Components and Business Entity Components. These terms will be explained later in this article.
Figure 1: Access and representation of data in distributed applications
Most applications store data in a relational database. In addition, there are other data stored methods, but this article focuses on the way .NET application and relational database interaction, do not specifically discuss how it interacts with data in other data stores such as plane files, non-relational databases.
This article clearly distinguishes the maintenance logic and the data itself. The reasons why they will remain logical and data are as follows:
Independent data hold components can isolate the application to the data source name, connection information, field name, and other database related content. Many applications now use loosely coupled, messaging techniques such as XML Web Services, Microsoft Message Queue (also known as MSMQ). These applications typically communicate through delivery of business documents rather than delivery.
Note: For the introduction to XML Web Services, see the article in MSDN® Magazine 2002 March.
.NET Web Services: Web Methods Make It Easy to Publish Your App's Interface over the Internet. For more information on message queues, see "Message Queuing overview".
In order to distinguish the maintenance logic and the data itself, this paper proposes two different component types.
Data Access Logic Components. Data Access Logic components retrieve data from the database and save entity data back to the database. Data Access Logic components also contain all business logic required to implement data-related operations. Business entity components. Data is used to represent business entities in the real world of products, orders. In the application, there are many ways such as this business entity, such as XML, DataSet, object-oriented custom class, etc., depending on the physical and logical design restrictions of the application. It will be discussed in detail later in this article.
Data Access Logic Components
Data Access Logical Components Represents the method of performing the following tasks for the database:
Create records in the database to read the records in the database and return the business entity data to the modified business entity data update database in the modified business entity data update database to delete records in the database.
The method of performing the above tasks is often referred to as "crud" method, which is an abbreviation word consisting of the first letters of each task.
Data Access Logic components also provide methods for implementing business logic for databases. For example, data access logic components may contain a method of finding the highest sales in the directory.
Typically, the data access logic component accesses a single database and encapsulates data related operations for one table or a set of related tables in the database. For example, a data access logic component can be defined to handle the Customer table and the Address table in the database, and simultaneously define another data access logic component to process the OrderS table and the OrderDetails table. This article will discuss design decisions to map data access logic components to database tables. Business entity
Each data access logic component processes a specific type of business entity. For example, a Customer Data Access Logic component processes a Customer business entity. Represents a lot of ways to business entities, depending on the following factors:
Do you need to bind business entity data to the controls in the Microsoft Windows® form or ASP.NET page? Do you need to perform sorting or searching for business entity data? Is the application handle a business entity each time, or usually handled a set of business entities? Is it a local deployment or a remote deployment application? Does XML Web Services use this business entity? What is the importance of non-functional requirements such as performance, scaling, maintenance, and programming convenience?
This article will outline the advantages and disadvantages of the following implementation options:
XML. Use an XML string or an XML document object model (DOM) object to represent business entity data. XML is an open and flexible data representation, which can be used to integrate various types of applications. DataSet. DataSet is a table that is cached in memory, which is obtained from a relational database or an XML document. Data Access Logic components can use DataSet to represent business entity data retrieved from the database, and you can use the DataSet in your application. For the introduction of DataSet, see "Introducing ADO.NET" in .NET Data Access Architecture Guide. There is a type of DataSet. Type DataSet is a class inherited from the ADO.NET DataSet class, which provides a strict type, event, and properties for columns in the access table and DataSet. Business entity components. This is a custom class that represents various business entity types. You can define a field that saves business entity data and defines the properties disclosed to the client application to the client application, and then use the field defined in this class to encapsulate simple business logic. This option does not implement data delivery with the underlying data access logic components via the CRUD method, but communicates directly with the data access logic component through the client application to perform the CRUD operation. Business entity components with CRUD behavior. Define a custom entity class as described above, and implements the Crud method of the underlying data access logic component associated with this business entity.
Note: If you want to use data in a more object-oriented manner, another alternative method can be used, that is, a target holding layer based on the reflection function of the public language running library. You can create a schema that uses reflection to read object properties, and use mapping files to describe mappings between objects and tables. However, to effectively implement the above method, a large amount of infrastructure code is required. This kind of investment may be accepted for ISV and solution providers, but it is not feasible for most organizations. The discussion of this aspect beyond the scope of this article, which is no longer discussed.
Technical factor
Figure 2 shows some technical factors that affect data access logic components and business entities. This article will discuss these technical factors and provide relevant recommendations.
Figure 2: Technical factors affecting data access logic components and business entity design
Mapping relational data to business entities
The database typically contains a number of tables, and the relationship between these tables is implemented by primary keys and foreign keys. When the business entity is defined to indicate this data in the .NET application, you must determine how to map these tables to the business entity.
Consider the imaginary retailer database shown in Figure 3.
Figure 3: Table relationship in the imaginary relationship database The following table summarizes the relationship type in the sample database.
Relationship Type Example Description A pair of Customer: AddressCustomer: ORDER A customer can have multiple addresses, such as delivery addresses, billing receiving addresses, contact addresses, etc. A customer can have multiple orders. Multi-to-many ORDER: Product One order can contain many products, each representing a single line from the OrderDetails table. Similarly, a product can also appear in many orders.
When defining a business entity to create an information model in a database, you should consider how to use this information in your application. The core business entity that encapsulates your application, rather than defining a separate business entity for each table.
Typical operations in this imaginary retailer's application are as follows:
Get (or Update) the information of the customer (including address) Get the customer's order list Get the list of subscription items list to create a new order to get (or update) one or a set of products
To meet these applications requirements, the application is to handle three logical business entities: Customer, Order, and Product. For each business entity, a separate data access logic component will be defined, as shown below:
Customer Data Access Logic Components. This class will provide services to the Customer Table and the data table in the Address table. Order data access logic components. This class will serve and modify the data of the ORDER table and the ORDERDetails table. Product data access logic components. This class will serve and modify the data in the Product table.
Figure 4 shows the relationship between these data access logic components and tables in the database represented.
Figure 4: Data access logic components defined to the .NET application disclosure data
For instructions on how to implement data access logic components, see Data Access Logic Components later in this article.
Recommendations for mapping relational data to business entities
To map relational data to business entities, consider the following suggestions:
Take some time to analyze your application's logical business entity and create a model, do not define a separate business entity for each table. One way to establish an application's work mode model is to use a Unified Modeling Language (UML). UML is a form design annotation that creates an object model in an object-oriented application and obtains how objects represent automatic processes, human-machine interactions, and associated information. For more information, see Modeling Your Application and Data. Do not define a separate business entity to indicate a multi-parallel table in the database, which can be disclosed by the method implemented in the data access logic component. For example, the ORDERDETAILS table in the previous example is not mapped to a separate business entity, but is a multi-to-many relationship between the ORDER and the Product Table by encapsulating the ORDERDetails table in the ORDER data access logic component. If you have a method of returning a specific service entity, put these methods in the data access logic component corresponding to this type. For example, when retrieving all of a customer's full order, the return value is the ORDER type, so this function should be implemented in the ORDER data access logic component. Conversely, this feature should be implemented in the Customer Data Access Logic component when retrieving all customers of a particular product. Data Access Logic components typically access data from a single data source. When data is needed to aggregate multiple data sources, it is recommended to define a data access logic component for accessing each data source, which can be called by a higher level service process component capable of performing aggregation tasks. It is recommended to use this method for two:
Transaction Management Concentrates in business process components, no need to explicitly control by data access logic components. If you access multiple data sources through a data access logic component, you need to access the logical components as the root of transaction processing, which gives additional system overhead to only the functionality of reading data. Usually, it is not an application of all areas that need to be aggregated, and you can use this type separately by separating the data, you can use it as part of the aggregation when necessary. Implement data access logic components
Data Access Logic Components is a stateless class, that is, all messages exchangeable can be explained separately. There is no state between calls. Data Access Logic components provide one or more related tables for accessing a single database (in some cases that can be multiple databases, such as horizontal database partitions). Typically, these methods in the data access logic component will call the stored procedure to perform the appropriate operation.
One of the main objectives of data access logic components is to hide the calls and format features of the database from the call application. Data Access Logic Components provide packaged data access services for these applications. Specifically, data access logic components process the following implementation details:
Manage and Package Locking Mode Correctly Handle Security and Authorization Problems Correct Handling Transaction Problem Perform Data Page Inquiry Data Related Route For Non - transactional Data Query Realization Cache Policy (If applicable) Perform data stream processing and data serialization
Some of these problems will be discussed in detail later in this section.
Data Access Logic Components Application Scheme
Figure 5 shows how to call data access logic components from various application types (including Windows Forms, ASP.NET applications, XML Web Services, and business procedures). These calls can be locally based on the deployment of the application, or it can be remote.
Figure 5: Application Scheme for data access logic components (click thumbnails to view large images)
Implement data access logic components
Data Access Logic Components use ADO.NET to perform SQL statements or call stored procedures. For an example of a data access logic component class, see How to Define Data Access Logical Components in the appendix.
If your application contains multiple data access logic components, you can use a data access assistant component to simplify the implementation of data access logic components. This component can help manage database connections, perform SQL commands, and cache parameters. Data Access Logic Components still encapsulates the logic required to access specific service data, and the data access assistant component focuses on the development and data connection configuration of the data access API, thereby helping to reduce the repetition of the code. Microsoft provides Data Access Application Block for .NET, which is used as a universal data access assistant component when you use the Microsoft SQL ServerTM database. Figure 6 shows a method of assisting data access logic components using a data access assistant component.
Figure 6: Implementing data access logic components using data access assistant components
When there is a utility feature of all data access logic components, a basic class can be defined to inherit and extend data access logic components.
Design data access logic components class as an unanimous interface that can provide different types of clients. If the data access logic component is designed to be compatible with the implementation requirements of the current and potential business process, the number of additional interfaces, contact surfaces, or mapping layers that must be implemented can be reduced.
To support a wide range of business processes and applications, consider the following techniques to incorporate data into and out of data access logic component methods:
The method of transmitting business entity data to data access logic components. You can deliver data in a variety of different format: as a series of scalar values, as an XML string, as a DataSet or as a custom business entity component. Returns business entity data from the method in the data access logic component. You can return data in a variety of different format: as an output parameter scalar value, as an XML string, as a DataSet, as a custom business entity component or a data reader.
The following sections will illustrate the advantages and disadvantages of access to business entity data into and outgoing data access logic components, and each way. This information helps you choose according to your own specific application solution. Transfer scalar values as input and output
The advantages of this method are as follows:
abstract. The calling program only needs to know the data defined for the business entity, without having to know the specific type or specific structure of the business entity. Serialization. The scalar value itself supports serialization. High memory use efficiency. Scalar values are only transmitted actually required data. performance. When the instance data is processed, the scalar value has higher performance than other methods described herein.
The disadvantage of this method is as follows:
Tight coupling and maintenance. Architecture changes may need to modify the method signature, which affects the calling code. Entity collection. To save or update multiple entities to data access logic components, multiple separate methods must be called. This will have a big impact on the distributed environment. Support open concurrency. To support open concurrency, you must define the timestamp column in the database and use it as part of the data.
Transfer XML strings as input and output
The advantages of this method are as follows:
Loosely coupled. The calling program only needs to know the data defined for the business entity and the architecture for providing metadata for business entities. integrated. Using XML can support call programs implemented in a variety of ways (for example, .NET applications, BizTalk Orchestration rules, and third-party business rules engine). Business entity collection. An XML string can contain data from multiple business entities. Serialization. The string itself supports serialization.
The disadvantage of this method is as follows:
The XML string is required to re-analyze. The XML string must be re-analyzed at the receiving end. Very large XML string affects performance. The memory is used low. The XML string is more cumbersome and thus reducing memory usage efficiency when delivering a lot of data. Support open concurrency. To support open concurrency, you must define the timestamp column in the database and use it as part of XML data.
Pass DataSet as input and output
The advantages of this method are as follows:
Inherent function. DataSet provides built-in features that can handle open concurrency (and data adapters) and support complex data structures. In addition, a type of DataSet also provides data verification support. Business entity collection. DataSet is designed for complex relationship collections, so it is not necessary to write a custom code to implement this. maintain. Changing the schema does not affect the method signature. However, if the type of DataSet and the assembly used have a strict name, you must use the publisher policy in the new version, or use the publisher policy in the global assembly cache, or define one
The disadvantage of this method is as follows:
performance. Instantiation and Sending DataSet will increase the runtime burden. Indicates a single business entity. DataSet is designed for processing a set of data. If your application is primarily processed by instance data, the scalar value or custom entity is a better way, the latter does not affect performance.
Transfer custom business entity components as input and output
The advantages of this method are as follows:
maintain. Changing the schema does not affect the data access logic component method. However, if the business entity component is included in a strictly named program set, the same problem as a type of Dataset occurs. Business entity collection. The array of custom business entity components can be incorporated and transmitted.
The disadvantage of this method is as follows:
Support open concurrency. To facilitate open concurrency, you must define the timestamp column in the database and use it as part of the instance data. Integrated restrictions. When using a custom business entity component as a data access logic component, the calling program must know the type of business entity, which will limit the integration of the calling program that does not use .NET. However, if the calling program uses a custom business entity component as the output of the data access logic component, the above problem does not limit the integration. For example, the web method can return a custom traffic entity component returned from the data access logic component and automatically sequence the service entity component to XML using XML serialization. Return the data reader as the output
The advantages of this method are as follows:
performance. This method has a performance advantage when it is necessary to quickly present data, and can use the representation layer code deployment data access logic components.
The disadvantage of this method is as follows:
Remotely. It is recommended not to use a data reader in a remote scheme because it may keep the client application with the database for a long time.
Cooperate with the use of data access logic components and stored procedures
Many data access tasks supported by data access logic components can be performed using stored procedures.
advantage
The stored procedure can usually improve performance because the database is capable of optimizing the data access plan used by the stored procedure and reuse the schedule for future reuse. The security protection of each stored procedure can be set in the database. The administrator can grant the client to perform permissions for a stored procedure without granting any basic table access. The stored procedure can simplify maintenance because modifying the stored procedure is often easier than the hardcoded SQL statement in the components deployed in the modification. However, as the business logic implemented in the stored procedure increases, the above advantages will gradually weaken. The stored procedure increases the degree of abstraction from the underlying database architecture. The details of the client of the stored procedure and the stored procedures are separated from each other. The stored procedure reduces network traffic. The application can perform SQL statements at approval without having to send multiple SQL requests.
Although the stored procedure has the above advantages, some cases are not suitable for use of stored procedures.
Disadvantage
If the logic is implemented in the stored procedure, the application involving extensive business logic and processing may bring overload to the server. Such processing includes data transfer, data traversal, data conversion, and large computational amount operations. Such processing should be moved to business processes or data access logic components, which have better scalability than database servers. Do not put all business logic in the stored procedure. If you must modify business logic in T-SQL, the maintenance and flexibility of the application will be a problem. For example, ISV applications that support multiple RDBMS should not maintain storage procedures for each system. Typically, writing and maintenance of stored procedures is a special skill, not all developers can master. This will cause the bottleneck of the project development plan.
Advice to use data access logical components and stored procedures
Consider the following suggestions when using the data access logic component and the stored procedure:
Public stored procedure. Data access logic components should be only components disclosed to database architecture information such as stored procedure name, parameters, tables, and fields. Business entity should not be needed or dependent on the database architecture. The storage procedure is associated with the data access logic component. Each stored procedure should only be called by a data access logic component and should be associated with the data access logic component calling it. For example, suppose a customer orders for a retailer. You can write a stored procedure named ORDERISERT for creating an order in the database. In your application, you must determine whether you call the stored procedure from the Customer Data Access Logic component or from the Order data access logic component. ORDER Data Access Logic Component Processes all tasks related to order, while Customer Data Access Logical Components handle customer name, address, etc., so it is best to use the former. Name stored procedure. When the stored procedure to be used to use the data access logic component, the selected stored procedure name should emphasize the data access logic components associated with it. This naming method helps to identify which component calls which stored procedures, and provides a method for logically group stored procedures in SQL Enterprise Manager. For example, you can write a stored procedure called CustomerInsert, CustomerUpdate, CustomergetByCustomerid, CustomergetByCustomerid, CustomerDelete, and then provides CustomergetAllinRegion, and then provides a more specific stored procedures such as CustomergetAllinRegion to support your application. Note: Do not use the prefix SP_ in front of the stored procedure name, which reduces performance. When a stored procedure starting with SP_, SQL Server always checks the master database, even if the stored procedure is defined by the database name.
Solve security issues. If you accept user input to dynamically perform a query, do not create a string by no connection value using the parameters. If you perform a result string using sp_execute, or not using sp_executesql parameter support, you should also avoid using a string connection during the stored procedure.
Manage locking and concurrency
Some applications use the "Last IN WINS) method when updating database data. Using the "Back" method to update the database when the update is compared to the original record, it may overwrite all the changes made by other users since the last refresh record. However, sometimes the application needs to determine whether the data has been changed since the initial read before performing the update.
Data Access Logic components can manage code that is locked and concurrent. There are two ways to manage locking and concurrency:
Conservative concurrency. Users who read a row of data for updates can set a lock in the data source. Any other users cannot change the row before the user is unlocked. Open concurrent. The user does not lock the line when reading a row data. Other users can freely access the line at the same time. When a user wants to update a row data, the application must determine if other users have changed since the row is read. Try updating records that have been changed will result in concurrent conflicts.
Use conservative concurrency
Conservative concurrency is mainly used for data contention and the cost of protecting data by locking to protect the cost of rollback transactions when concurrent; If the lock time is short (for example, in the programmed record), the conservative concurrency effect is achieved.
Conservative concurrency requires a persistent connection to the database, and because the record may be locked for a long time, it is not possible to provide scalable performance when the user interacts with the data.
Use open concurrent
Open concurrent applications are available for data stronality or require read only access to data. Open concurrency can reduce the number of locks required to reduce the load of the database server and improve the performance of the database.
Open concurrency is widely used in .NET to meet the needs of mobile and offline applications. In this case, long-term locking data is not feasible. In addition, keep the recording lock also requires a persistent connection to the database server, which is impossible in offline applications.
Test open concurrent conflict
There are many ways to test open concurrent conflicts:
Use a distributed timestamp. Distributed timestamps are suitable for environments that do not require coordination. Add a timestamp column or version column in each table of the database. The timestamp column returns together with the query on the table content. When trying to update, the timestamp value in the database will be compared to the original timestamp value in the modified row. If the two values match, execute the update, and the timestamp column is updated to the current time to reflect the update. An open concurrent conflict occurs if the two values do not match. Retain a copy of the original data value. Retain a copy of the original data value when you query the data of the database. When updating the database, check if the current value of the database matches the original value. The original value is saved in the DataSet, when updating the database, the data adapter can use the original value to perform an open concurrent check. Use the concentrated timestamp. Define a set of timestamp tables in the database to record updates to any row in any table. For example, the timestamp table can display the following information: "John updated the line 1234 in Table XYZ at 2:56 pm March 26, 2002. Concentrated timestamps are suitable for check out programs and some offline client scenarios, which may need to be clearly locked owners and alternative management. In addition, the concentrated timestamp can also provide an audit as needed.
Manually achieve open concurrency
Consider the following SQL query:
Select Column1, Column2, Column3 from Table1
To test an open concurrent conflict while updating Table1, you can issue the following UPDATE statement:
Update table1 set colorn1 = @ newvalueColumn1,
Set column2 = @ newvalueColumn2,
Set column3 = @ newvalueColumn3
Where column1 = @ oldvalueColumn1 and
Column2 = @ oldvaluecolumn2 and
Column3 = @ OldValueColumn3
If the original value matches the value in the database, the update is performed. If a value is modified, the WHERE clause will not find the corresponding match, so that the update will not modify the row. You can change this technology a slightly change, ie, only apply the WHERE clause for a particular column, so that the data is not overwritten if a specific field has been updated since the last query.
Note: Always return a value of a row in a unique identifier, such as a primary keyword for the WHERE clause of the UPDATE statement. This ensures that the UPDATE statement updates the correct row.
If the column in the data source allows null values, you may need to extend the WHERE clause to check the empty references that match the local table and the data source. For example, the following Update statement will verify that the empty reference (or value) in the local row is still matched with the empty reference (or value) in the data source.
Update table1 set colorn1 = @ newcolumn1value
Where (@ oldcolumn1value is null and color) or column1 =
@ OldColumn1Value
Use data adapter and DataSet to achieve open concurrency
An open concurrent conflict can be informing your application using the DataAdapter.RowUpdated event to notify your application. Whenever trying to update the modified row in the DataSet, RowUpdated events will be triggered. You can use the RowUpdated event to add special processing code, including processing, processing, add custom error information, and add retry logic.
The RowUpdated event handler receives a RowUpdatedEventArgs object that has a RECORDSAFFECTED property that can display how much it affects the update command for a modified row in the table. If the update command is set to test open concurrency, the RecordSaffected property will be 0 when an open concurrent conflict occurs. Set the RowUpdatedEventArgs.status property to indicate the operations to take; for example, you can set this property to UpdateStatus.skipCurrentrow to skip updates to the current row, but continue to update other rows in the update command. For more information on the RowUpdated event, see Working With DataAdapter Events. Another way to test concurrent errors using a data adapter is to set the DataAPter.ContinueUpdateOnError property to True before calling the Update method. After completing the update, call the getRRORS method of the DataTable object to determine which rows have occurred. Then, use these rows of ROWERROR properties to find specific detailed error messages. For more information on how to handle the wrong error, see Adding and Reading Row Error Information.
The following code example shows how the Customer data access logic component checks concurrent conflicts. This example assumes that the client retrieves a DataSet and modifies the data, and then passes the DataSet to the UpdateCustomer method in the data access logic component. The UPDATECUSTOMER method will update the corresponding customer record by calling the following stored procedures; the store can update the customer record only when the customer ID is not modified.
Create Procedure Customerupdate
{
@Companyname varchar (30),
@eldcuStomerid Varchar (10),
@OLDCompanyName Varchar (30)
}
AS
Update Customers Set CompanyName = @companyname
Where customerid = @OLDCUSTOMERID and companyNAME = @OLDCompanyName
Go
In the UpdateCustomer method, the following code example sets a data adapter's UpdateCommand property to test open concurrent, then use the RowUpdated event to test open concurrent conflicts. If you encounter an open concurrent conflict, the application will indicate an open concurrent conflict by setting RowError to be updated. Note that the parameter values passing to the WHERE clause in the Update command are mapped to the original values of each corresponding column in the DataSet.
// CustomerDalc class UpdateCustomer method
Public void UpdateCustomer (Dataset DSCustomer)
{
/ / Connect to the Northwind database
SqlConnection cnnorthwind = New SqlConnection
"Data Source = localhost; integrated security = sspi; initial
Catalog = northwind ");
// Create a data adapter to access the Customers table in Northwind
Sqldataadapter Da = new SqlDataAdapter ();
/ / Set the Update command of the data adapter to call the stored procedure "UpdateCustomer"
Da.UpdateCommand = New SQLCOMMAND ("Customerupdate", cnnorthwind; da.UpdateCommand.commandtype = commandtype.storedProcedure;
/ / Add two parameters to the UPDATE command of the data adapter,
/ / Specify information for WHERE clauses (used to check open concurrent conflicts)
Da.UpdateCommand.Parameters.Add ("@ companiesName", Sqldbtype.nvarchar, 30,
"CompanyName");
// Specify the original value of Customerid as the first WHERE clause parameter
Sqlparameter myparm = da.updateCommand.Parameters.Add (
"@OLDCUSTOMERID", SQLDBTYPE.NCHAR, 5,
Customerid ");
myparm.sourceversion = DATAROWVERSION.ORIGINAL;
// Specify the original value of CustomerName as the second WHERE clause parameter
myparm = da.UpdateCommand.Parameters.Add (
"@OLDCompanyName", Sqldbtype.nvarchar, 30,
"CompanyName");
myparm.sourceversion = DATAROWVERSION.ORIGINAL;
/ / Add a handler for the RowUpdated event
Da.RowUpdated = new sqlrowupdatedEventHandler (onrowupdated);
/ / Update the database
Da.Update (DS, "Customers");
Foreach (DataRow Myrow In Ds.Tables ["Customers"]. ROWS
{
IF (Myrow.haserRRORS)
Console.Writeline (Myrow [0] " Myrow.RowError);
}
}
// How to handle the RowUpdated event. If you register the event but don't process it,
// causes an SQL exception.
Protected static void onrowupdated (Object Sender, SqlrowUpdatedEventArgs
ARGS)
{
IF (args.recordsaffected == 0)
{
Args.row.rowError = "Encountered Conflict Conflict";
Args.status = updatestatus.skipcurrentrow;
}
}
When performing multiple SQL statements during a SQL Server store, the SET NOCOUNT ON option can be used for performance reasons. This option will prohibit SQL Server to return a message to the client each time you perform a statement, so that network traffic can be reduced. However, this will not be able to check the RecordsAffected attribute as the previous code example. The RecordSaffected property will always be 1. Another method is to return the @@ rowcount function (or specify it as an output parameter) during the stored procedure; @@ rowcount contains the number of records when the last statement is completed during the store, and even uses the set nocount on, This function will be updated. Therefore, if the previous SQL statement executed during the store is the actual UPDATE statement, and the @@ rowcount is specified as the return value, the application code can be modified as follows: // Add another parameter to the UPDATE command to the data adapter To receive the return value.
// You can name this parameter arbitrarily.
Myparm = da.updateCommand.Parameters.add ("@ rowcount", sqldbtype.int);
myparm.direction = parameterDirection.ReturnValue;
/ / Change the onrowupdated method to check the value of this parameter
// is not the RecordSaffected property.
Protected static void onrowupdated (Object Sender, SqlrowUpdatedEventArgs
ARGS)
{
IF (args.command.parameters ["@ rowcount"]. value == 0)
{
Args.row.rowError = "Encountered Conflict Conflict";
Args.status = updatestatus.skipcurrentrow;
}
}
COM interoperability
If you want the data access logic component class to be called by the COM client, it is recommended to define the data access logic component as described above and provide a package assembly. However, if you want the COM client to access data access logic components, consider the following suggestions:
Define this class and its members as public. Avoid using static members. Define an event-source interface in the hosted code. Provides a constructor that does not use parameters. Do not use overload methods, and use multiple names different methods. Use the interface to disclose common operation. Use properties to provide additional COM information for classes and members. All exceptions caused by .NET code include the HRESULT value. Use the automatic compatible data type in the method signature.
For more information on COM interoperability, see the Microsoft .NET / COM MIGRATION AND Interoperability guide.
Implement business entity
The business entity has the following features:
Business entities provide status programming access to business data and related functions (in some designs). Business entities can be built using data with complex architectures. This data typically comes from multiple related tables in the database. Business entity data can be passed as part of the I / O parameter of the business process. The business entity can be serialized to maintain their current state. For example, the application may need to store entity data in a local disk, a desktop database (if an application offline work) or message queue message. Business entities do not directly access the database. All database access is provided by associated data access logic components. Business entities do not start any type of transaction. Reasons for transaction reasons to use business entities to start.
As mentioned earlier in this article, there are many ways to represent business entities (from data-centric models to more object-oriented representations): XML Universal DataSet has type DataSet custom business entity components with CRUD behavior custom business entity components
The following sections describe how to use these formats to represent business entities. To help you determine the most suitable business entities in a particular environment, the following sections describe how to perform the following tasks for each business entity format:
Organizational business entity collection Binds business entity data to user interface control serialization business entity data in interlayer delivery business entity data
The following sections have considered applicability of each business entity for non-functional requirements (including performance, efficiency, scalability, and scalability).
Repositing business entity as XML
The following example shows how to represent a simple business entity as an XML. The business entity contains a product.
XML Version = "1.0"?>
Product>
For more information, see How to Use XML in the appendix to represent the collection and hierarchy of data.
When using XML to represent business entity data, consider the following principles:
Determining the XML document is a collection of a single business entity or containing a business entity. The previous example represents a single Product business entity. Uniquely identify the XML document using a namespace to avoid naming conflicts with other XML documents. The previous example uses the default namespace named URN: AuniquenameSpace. Select the appropriate name for the elements and attributes. The previous example uses the column name of the Product table but does not require this. You can choose a name that makes sense to your application. Use one of the following methods to retrieve your business entity in XML format:
If you are using SQL Server 2000, you can use the for XML clause during query or stored procedures. In performance test, use for XML only a little more faster than returning DataSet. Retrieve the DataSet and convert it to an XML stream or written in the format of the XML stream. This approach brings the creation of DataSet system overhead and additional conversion overhead (if converted). Build an XML document using an output parameter or a data reader. The data reader is the fastest way to retrieve multiple rows from the database, but the process associated with building XML may weaken this performance advantage.
For more information or performance considerations, see Performance Comparson: Data Access Techniques.
The advantages indicated by the business entity as XML are as follows:
Standard support. XML is the standard data representation of World Wide Web Consortium (W3C). For more information on this standard, see http://www.w3.org/xml. flexibility. XML can represent hierarchies and collections of information. For more information, see How to Use XML in the appendix to represent the collection and hierarchy of data. Interoperability. On all platforms, XML is ideal for exchange information with external parties and trading partners. If the XML data will be used by an ASP.NET application or Windows Form application, you can also load these XML data into a DataSet to use the data binding support provided by DataSet. The disadvantage of the business entity as XML is as follows:
Type fidelity. XML does not support type fidel. However, the XSD architecture can be used for simple data classification. Verify XML. To verify XML, you can analyze the code manually, or use the XSD architecture. But these two methods are relatively slow. For examples of how to verify XML using an XSD architecture, see How to verify XML using the XSD architecture. Display XML. You cannot automatically display XML data on the user interface. You can write a XSLT style sheet to convert the data to DataSet; but the writing of the style sheet is more troublesome. Another method is to convert XML to HTML or the like to display formats through the style sheet. For more information, see How to Program Applying Style Table in the .NET application in the appendix. Analysis XML. To analyze XML, you can use the XMLReader class provided by the Document Object Model (DOM) or Microsoft .NET Framework class library. XmlReader provides fast read-only for XML data, only forward access, while DOM can provide random read / write access, so more flexible. However, using the DOM analysis XML document is slower; you must create an XMLDocument instance (or another XML analyzer class) and load the entire XML file into memory. Sort XML. You cannot automatically sort XML data, and one of the following technologies should be used:
Provides data in advance in advance. This method does not support dynamically reordering data in the call application. Apply XSLT style sheet dynamically sorted data. If desired, you can use the DOM to change the sorting conditions in the XSLT style sheet. Convert XML data to DataSet and use the DataView object to sort and search the data element. Use a dedicated field. You cannot choose hidden information.
Repositing business entities as universal dataset
Universal DataSet is an instance of a DataSet class, which is defined in the system.data namespace of ADO.NET. The DataSet object contains one or more DataTable objects to indicate information that the data access logic component is retrieved from the database.
Figure 7 shows a general DataSet object for the Product business entity. The DataSet object has a DataTable for saving product information. The DataTable has a UniqueConstraint object that is used to mark the ProductID column as the main key. DataTable and UNIQUECONSTRAINT objects are created when creating DataSets in a data access logic component.
Figure 7: General DataSet for Product business entities
Figure 8 shows a general DataSet object for the Order business entity. This DataSet object has two DataTable objects, saves order information and order details, respectively. Each DataTable has a corresponding UNIQUECONSTRAINT object for identifying the primary key in the table. In addition, the DataSet has a RELATION object that is used to associate orders with orders. Figure 8: General DataSet for the Order business entity
The following code shows how to retrieve universal DataSet from the data access logic component, then bind the DataSet to the DataGrid control, and then pass the DataSet to the data access logic component to save the changes to the data:
// Create a ProductDalc object
ProductDalc DalcProduct = new productdalc ();
/ / Call a method for ProductDalc to get a DataSet that contains all product information
DataSet dsproducts = DalcProduct.getProducts ();
// Use the DataSet in the client. For example, bind the DataSet to the user interface control
DataGrid1.datasource = dsproducts.tables [0] .defaultView;
DataGrid1.databind ();
// Then, pass the updated DataSet to ProductDalc, will change
/ / Save to the database
DalcProduct.UpdateProducts (DSProducts);
You can also query and modify tables, constraints and relationships in DataSet at runtime. For more information, see Creating and Using DataSets.
The advantages of using business entities as universal DataSet are as follows:
flexibility. The DataSet can contain a collection of data, which can represent complex data relationships. Serialization. Data itself supports serialization when passed during the interlayer. Data binding. You can bind DataSet to any user interface controls for ASP.NET applications and Windows Forms applications. Sort and filter. You can use the DataView object sort and filter DataSet. Applications can create multiple DataView objects for the same DataSet to view data in different ways. Interchangeability with XML. You can read and write DataSet in XML format. This approach is useful in remote and offline applications, which can receive DataSet with XML format and then re-create the DataSet object locally. After the application is connected to the database, you can keep the DataSet as an XML format. The availability of metadata. You can provide complete metadata for DataSet in the form of an XSD architecture. You can also use the method in the DataSet, DataTable, DataColumn, the Constraint, and the Relation class to program the metadata for DataSet. Open concurrent. When updating data, you can use the data adapter and DataSet to easily perform an open concurrency check. Scalability. If a database architecture is modified, the method in the appropriate data access logic component can create a DataSet that contains the modified DataTable and DataRelation objects. Data Access Logic Component Method Sign does not change. You can modify the calling application to use these new elements in the DataSet.
The disadvantage of the business entity as a general DataSet is as follows:
The client code must access the data over a DataSet. To access tables in the DataSet, client code must use an integer index generator or a string index generator to index a DataTable collection. To access a specific column, you must use the column number or column name indexing the Datacolumn collection. The following example shows how to access the ProductName column of the first row in the Products table: // Get the first row of Dataset called DSPRODUCTS. Note that this collection is based on zero.
String str = (string) dsproducts.tables ["products"]. Rows [0] ["productname"];
...
Note: There is no compilation of these index builders here. If you specify an invalid table name, column name, or column type, it will capture the error at runtime. IntelliSense is not supported when using General DataSet.
The cost of instantiation and sealing processing is high. DataSet needs to create multiple sub-objects (DataTable, DataRow, and Datacolumn), which means that DataSet takes longer than XML strings or custom entity components when instantiation and encapsulation processing. As the amount of data increases, the system overhead of creating a DataSet internal structure will be significantly less than the overhead required to populate data into the DataSet, so the relative performance of DataSet will increase. Special field. You cannot choose hidden information.
Repositing business entity as a type of DataSet
A type of DataSet is a class that contains stringent types, attributes, and types definitions to disclose data and metadata in the DataSet. For examples of how to create a type of DataSet, see How to Create Type Dataset in the appendix.
The advantages and disadvantages of type DataSet are listed below. Note that the instantiation and sealing processing performance of a type of DataSet is basically the same as General DataSet.
The advantages of expressed business entities as a type of DataSet are as follows:
Easy to read. To access tables and columns in type DataSet, you can use a type of method and properties, as shown in the following code: ...
/ / Get the first line of the Type Dataset called DSProducts called Dsproducts
// product name. Note that this collection is based on zero.
String str = dsproducts.products [0] .productname;
...
In this example, DSProducts are an instance of a type of DataSet. The DataSet has a DataTable that is disclosed by an attribute named product. The columns in the DATATABLE are disclosed by ProductName and other attributes, and the latter returns the corresponding data type (not just returns object). Providing types of methods and attributes make it easier to use with type DataSet than using universal DataSet. IntelliSense will be available when using a type of DataSet. Compile time type check. The invalid table name and column name will be instead of compile time instead of running at runtime.
The disadvantage of the business entity as a type of DataSet is as follows:
deploy. The assembly that includes a type of DataSet class must be deployed to all layers using the business entity. Support Enterprise Services (COM ) calls. If a type of DataSet is used by the COM client, you must provide a stringent name for the assembly containing the type of DataSet class, and must be registered on the client computer. Typically, the assembly is installed in the global assembly cache. These are also the steps required to customize the entity class, as described later. Scalability problem. If the database architecture is modified, you may need to regenerate a type of DataSet class to support the new architecture. Regeneration The process will not retain any custom code implemented in a type of DataSet class. The assembly that contains a type of DataSet class must be redistributed to all client applications. Instantiate. You cannot use the New operator to instantiate the type. inherit. Type DataSet must inherit from DataSet class, which disables any other basic class. Define custom business entity components
Represents a custom class for business entities typically contains the following members:
A dedicated field for data for the business entity locally. These fields save a snapshot of database data when data access logic components retrieve data from the database. Public properties for accessing the status of entities and subsets and hierarchies of data within entities. The names of these attributes can be the same as the column names of the database, but this is not an absolute requirement. You can select the property name according to your application, without having to use the name in the database. Method and attributes for performing localization processing using data in entity components. Events used to notify the internal state of the entity component.
Figure 9 shows a method of using a custom entity class. Note that the entity class does not know the data access logical component or the underlying database; all database access is performed by the data access logic component to centralized data access policies and business logic. Further, the method of transmitting traffic in the interlayer is not directly related to the format indicating the service entity; for example, the service entity can be represented locally as an object, and the service is used in another method (such as scalar value or XML). Entity data is passed to other layers.
Figure 9: Customizing the role of business entity components (click thumbnail to view large images)
Define recommendations for custom business entity components
When implementing custom entity components, consider the following suggestions:
Select the use structure or use the class. For a simple business entity that does not include a hierarchical data or a collection, you can consider a structure to represent a business entity. For complex business entities or service entities that require inheritance, the entity can be defined as classes. For two types of structures and classes, see Structures and Classes. Indicates the status of the business entity. For numbers, strings, etc., you can define the fields using equivalent .NET data types. See how to define business entity components in the appendix on how to define a custom entity. Represents subsets and hierarchies in custom business entity components. There are two ways to represent subsets and hierarchies of data in custom entities:
.NET set (such as ArrayList). The .NET set class provides a convenient programming model for the size of the size, also provides built-in support to bind data binding to user interface controls. DataSet. DataSet is adapted to store a collection and hierarchy of data from the relational database or XML file. Also, if you need to filter, sort or bind subsequent collections, you should prefer DataSet. See how to represent a collection of data in a custom entity and a hierarchy, see How to represent the collection and hierarchies of data in the custom entity in the appendix. Support the data binding of the user interface client. If the custom entity will be used by the user interface and want to utilize the automatic data binding, it may be necessary to implement data binding in a custom entity. Consider the following scenarios:
The data binding in the Windows form. You can bind the data of the entity instance to the control without having to implement the data binding interface in a custom entity. You can also bind an entity array or .NET collection. Data binding in the web form. If you do not implement an IbindingList interface, you cannot bind the data of the entity instance to the controls in the web form. However, if you just want to bind a collection, you can use an array or .NET collection without having to implement an IBINDINGLIST interface in a custom entity. See how to bind custom entities to code examples of user interface controls, see How to Bind Business Entity Components to User Interface Controls in Appendix. Events that open internal data changes. Open events can get a rich client user interface design because it allows you to refresh regardless of where the data is displayed. The event should only be used for internal state instead of data on the server. For an explanation of how to disclose an event in a custom entity class, see How to disclose events in the Appendix in the business entity component. Enable business entities to serialize. The business entity can be serialized to keep the status of the business entity in an intermediate state without performing a database interaction. This makes it easy to get offline applications and design of complex user interface, that is, do not affect business data before completion. There are two types of serialization: XML serialization is performed using the XMLSerializer class. If you only need to sequence the public field and public read / write properties to XML, you can use XML serialization. Note that if the business entity data is returned from the web service, the object will automatically serialize XML through XML serialization. You can perform XML serialization for business entities without any additional code in entity. However, only common fields and public read / write properties in the object are sequence to XML. Special fields, index builders, dedicated properties, read-only properties, and object maps are not serialized. You can use the attribute control results XML using the properties in the custom entity. For more information about the sequence of custom entity components to XML format, see How to Sequence in the appendix to XML format. Use the BinaryFormatter or the SOAPFormatter class to format serialization. If you need all public fields, dedicated fields, and object maps of the serialized object, or you need to transfer the entity components between the remote server, you can use the format sequence. Format classes will serialize all public and dedicated fields and properties of the object. BinaryFormatter uses the object sequence to binary format, and SOAPFormatter will sequence the object to the SOAP format. Serialization using BinaryFormatter is fast than serialization speed using SOAPFormatter. To use any format class, you must mark the entity class as the [Serializable] property. If you need explicit control serialization format, your class must implement the iSerializable interface. For more information on how to use format serialization, see How to Series Series Series Sequence to Binary Formats in Appendix and how to sequence the business entity components into SOAP formats.
Note: When restoring a sequence, the default constructor is not called. Add this constraint to the restore serialization is due to performance considerations.
The advantages of defining custom entities are as follows:
Easy to read. To access data in a custom entity class, you can use a type of method and properties, as shown by the following code: // Create a productDalc object
ProductDalc DalcProduct = new productdalc ();
// Create and populate a productTentity object using the ProductDalc object.
// This code assumes that the ProductDalc class has a method called getProduct.
/ / This method uses the Product ID as a parameter (21 in this case) and returns one
// contains the ProductEry object of all the data of the product.
Product = DalcProduct.getProduct (21); // Change the product name of the product
Aproduct.ProductName = "rosted coffee beans";
In the above example, the product is an instance of a custom entity class named Productity. The ProductDalc class has a method called getProduct, the latter creates a productTentity object, populates the data of a particular product to the object, and then returns the ProductIns object. Calling an application You can use productName and other attributes to access data in the Productity object, and can call the method to operate the object. Package. Custom entities can include methods to package simple business rules. These methods operate the business entity data in the entity component, rather than accessing real-time data in the database. Consider the following example: // Call a method defined in the ProducTentity class.
Aproduct.incReaseUnitpriceby (1.50);
In the above example, calling the application calls a method called IncreaseUnitPriceBy to the ProductIns object. This change is not permanent before calling the application to call the PRODUCTDALC object to save the ProductIns object to the database. Build a model of complex systems. When building a complex domain problem (there is a lot of interactions between different business entities), a custom entity class can be defined to hide complexity behind the well-defined class interface. Localization verification. Custom entity classes can perform simple verification tests in their attribute accessors to detect invalid business entity data. For more information, see How to verify the data in the attribute accessor of the business entity component. Special field. You can hide information that does not want to disclose to the calling program.
The disadvantage of defining a custom entity is as follows:
Business entity collection. Custom entities represent a single business entity, not a collection of business entities. To save multiple business entities, calling an application must create an array or a .NET collection. Serialization. You must implement your own serialization mechanism in a custom entity. You can use properties to control the serialization of entity components, or you can control your serialization by implementing the iSerializable interface. Represents complex relationships and hierarchies in business entities. You must implement your own relationship and hierarchy representation mechanism in the business entity component. As mentioned earlier, DataSet is usually the easiest way to achieve this. Search and sort data. You must define your own mechanism to support the entity search and sort. For example, you can save the IComparable interface to save the entity component in a sortedList collection or a HashTable collection. deploy. You must deploy an assembly that contains custom entities in all physical layer. Support Enterprise Services (COM ) clients. If a custom entity will be used by the COM client, you must provide a stringent name for the assembly containing the entity and must be registered on the client computer. Typically, the assembly is installed in the global assembly cache. Scalability problem. If the database architecture is modified, you may need to modify the custom entity class and redeploy the assembly.
Define custom business entity components with CRUD behavior
When defining a custom entity, methods can be provided to fully encapsulate the Crudic operation of accessing the logic components of the underlying data. This is a comparing traditional object-oriented approach, which may apply to complex object domains. Client applications no longer directly access data access logic component classes, but create an entity component and call the Crud method for the entity component. These methods will call the base data access logic components.
Figure 10 shows the role of a custom entity class with CRUD behavior.
Figure 10: Role of custom business entity components with CRUD behavior (click thumbnail to view large images) Define the advantages of custom entity classes with CRUD behavior as follows:
Package. Custom entities can package the operations defined by the underlying data access logic components. Interface with the calling program. The calling program must only process an interface to hold business entity data. You don't have to access data access logic components directly. Special field. You can hide information that does not want to disclose to the calling program.
The disadvantage of defining custom entity classes with CRUD behavior is as follows:
Handling business entities collection. The method in custom entities belongs to a single business entity instance. To support business entities, you can define a static method to read or return a group or a collection of entity components. Development time is long. Traditional object-oriented methods are usually more designed and developed than using existing objects such as DataSet.
Suggestions indicating data and delivery between the layers
It is not necessary to pass the data in your application and how to pass data between the layers is not necessarily the same. However, a consistent and limited format can reduce the need for additional conversion layers, thereby improving performance and facilitating maintenance.
The data format should be selected according to its own specific application requirements and operational data. There is no universal representation, especially since many applications today need to support multiple call programs. However, we still recommend following the following general principles:
If your application is primarily handled and requires sort, search, and data binding, it is recommended to use DataSet. However, if the application handles instance data, the effect of the scalar value will be better. If your application is primarily processed by instance data, custom business entity components may be the best choice because they can eliminate a DataSet representing system overhead when a line. In most cases, the application should be designed to use the XML document, DataSet, etc., to data-centered format. Multiple clients can be easily supported by DataSet flexibility and inherent functions to make it easier to support multiple clients, reducing the number of custom code and using programming APIs well known to most developers. Although there are many advantages to object-oriented manner, custom encoding complex business entities will increase the number of developments and maintenance costs.
Transaction processing
Most applications today need to support transaction processing to maintain system data integrity. There are a variety of management methods for transaction processing, but each method can be attributed to one of the following two basic programming models:
Manual transaction processing. Write the code using the ADO.NET or Transact-SQL transaction support function directly during component code or stored procedure. Automatic transaction processing. Use the Enterprise Service (COM ) to add a declarative property to the .NET class to specify the transactional requirements of the object at runtime. Using this model can easily configure multiple components to perform work in the same transaction.
This section provides some guiding principles and recommendations to help you implement transactional support in data access logic components and business entity components. See .NET Data Access Architecture Guide for transactional examples and more in-depth discussions.
Realize transaction processing
In most environments, transaction processing is the business process instead of data access logic components or business entity components. This is because business processes generally require transactions to handle transfers, but not just a single business entity.
However, it is also possible to perform transactional operations on a single business entity with help with high-level business processes. For example, to add a new customer to the database you discussed earlier, you must do the following:
Insert a new line in the Customer table. Insert a new line or more lines in the Address table.
The client will be added to the database only after these two operations are successful. If the Customer business entity does not become part of the larger business process that starts the transaction, you should use manual transaction in the Customer business entity. Manual transaction is not required to communicate between processes between the Microsoft Distributed Transaction Coordinator (DTC), so there is much more faster than Automatic transaction.
Figure 11 shows a method of determining using manual transaction or automatic transaction processing. Due to the system overhead of COM transaction processing, it is recommended to put transaction to the database and control transaction behavior (if possible) during the stored procedure. Figure 11: Determine how to implement transaction
Note: If you call from ASP.NET-based clients, and there is no service procedure for startling transaction, you may start the transaction from the ASP.NET code. This design is not good; you must never start transaction processing from ASP.NET-based clients, and the display should be separated from the business process. In addition, due to problems such as network hysteresis can also result in performance problems because it is the most common layer to be deployed on other layers.
Suggestions for manual transaction processing in data access logic components
When implementing manual transaction processing in a data access logic component, consider the following suggestions:
Perform processing during the stored procedure as possible. Use Transact-SQL statements Begin Transaction, End Transaction, and Rollback Transaction Control transaction. For code examples, see "How to Perform Transactions with Transact-SQL" in .NET Data Access Architecture Guide. If the stored procedure is not used, the data access logic components are not called from the business process, you can use ADO.NET to program control transaction. For code examples, see "How To Code Ado.net Manual Transactions" in .NET Data Access Architecture Guide.
Recommendations for automated transaction processing in data access logic components
Although COM transaction processing brings some system overhead, Automatic transaction can provide a simpler programming mode than manual transaction, and automatic transaction processing must be used when transaction processing across multiple distributed data sources (work with DTC) . When implementing automatic transaction processing in the data access logic component, consider the following suggestions:
Data Access Logic Components must be inherited from the ServicedComponent class from the System.EnterpriseServices namespace. Note that all assemblies registered with COM services must have a strict name. For more information on strictly named assemblies, see Creating and use strong-named assembly. Use the Transaction (TransactionOption.supported property to annotate the data access logic component so that you can perform read / write operations in the same component. Unlike Transaction (TransactionOption.Required), this option avoids unnecessary system overhead without the need for transaction, while the former will always require transaction processing.
The following code example shows how to support automatic transaction processing in the data access logic component class:
Using system.enterprises;
Transaction (TransactionOption.supported)]
Public Class Customerdalc: ServicesDComponent
{
...
}
If automatic transaction is used, the data access logic component should indicate whether the operation is successful in transaction. If you want to implicate, you should use the AutoComplete property to comment your method and make an exception when the operation fails. If you want to explicitly indicate, call the setcomplete or setabort method to the ContextUtil class.
For more information on automatic transaction processing, see "Using Automatic Transactions" in .NET Data Access Architecture Guide. Automatic transaction processing in business entity components
When implementing a custom business entity component with behavior, automatic transaction processing can be used to specify transactional behavior of these objects. Recommendations for specifying business entity component transaction behavior using automatic transaction processing are identical to the proposal to implement automatic transaction processing in data access logic components.
Note: If the service entity component does not contain any business logic that is required to indicate whether it is successful in transaction, it can ignore the transaction environment. Customized business entity components do not need to inherit from Services; the transaction environment will continue its process, but physical components will ignore the transaction environment.
verification
You can verify data verification on many layers of the application. Each layer applies different types of validation:
Before submitting data, the client application can verify the business entity data locally. When using the XSD architecture to receive business documents, the business process can verify these documents. Data Access Logic Components and Storage procedures can verify data to ensure references and forced compliance with constraints and important business rules.
There are two types of verification:
Time verification. This is the verification performed at a specific time point. For example, verify it by the business process when receiving an XML document. Continuous verification. This is a verification that is continuously carried out in many different levels of the application. Examples of continuous verification include:
The user interface can specify the maximum length of the field to prevent the user from entering too long strings. DataSet can specify the maximum length of the data column. Customized business entity components can check, length check, non-air inspection, and other simple tests. Data access logic components, stored procedures, and database itself can perform similar tests to ensure their validity before saving data to the database.
Sometimes you might want to achieve additional aggregation processes or conversion processes. This approach may be useful when verifying and transition often changes, but will lose performance. For example, if an ISV wants to support two versions of the database architecture using the same component, you can create a separate component to perform verification and conversion between the two database architectures.
How to verify XML using XSD architecture
To verify an XML document using an XSD architecture, perform the following steps:
Create an XMLValidatingReader object as the package of the XMLTextReader object, as shown by the following code: 'Create an XMLValidatingReader object to read and verify product.xml
XMLTextReader Tr = New XMLTextReader ("Product.xml");
XmlvalidatingReader VR = New XmlValidatingReader (TR);
Enumerate the specified verification type by using the ValidationType. .NET Framework supports three types of XML authentication:
Document Type Definition (DTD); Specify ValidationType.dtd Microsoft XML Red Data (XDR) Architecture; Specify ValidationType.xdr W3C Standard XSD Architecture; Specify ValidationType.Schema The following code shows the use of validationType enumeration: vr.validationType = ValidationType.Schema ; 'Specify XSD architecture verification
Register a verification event handler method, as shown in the following code: vr.validationEventHandler = New ValidationEventHandler (MyHandlerMethod);
Provide an implementation of a verification event handler method, as shown in the following code: Public void myHandlerMethod (Object Sender, ValidationEventArgs E) {
Console.writeline ("Verification Error: E.MESSAGE);
}
Read and verify the document, as shown in the following code. Verify errors will be authenticated event handler methods. Try
{
While (Vr.Read ())
{
/ / Appropriate processing XML data ...
}
}
Catch (XMLEXCEPTION EX)
{
Console.writeline ("XMlexception:" EX.MESSAGE);
}
vr.close ();
How to verify data in attribute accessors of business entity components
The following code snippet shows how to make simple validation in the attribute enclosure of custom entities. If the verification test fails, you can issue an exception to display the nature of the problem. Regular expressions can also be used to verify specific data and formats in the attribute accessory collection.
Public Class ProductDalc
{
...
Public Short ReorderLevelLevel
{
Get {return reorderLevel;}
}
set
{
Value <0)
{
Throw New ArgumentOutofrangeException ("ReorderLevel cannot be negative.");
}
REORDERLEVEL = Value;
}
/ / Plus other members in the Productdalc class ...
}
Abnormal management
When the .NET application has an error, the usual suggestion is an exception instead of returning an error value from the method. This proposal suggests how you write data access logical components and business entity components. There are two very abnormalities:
Technology exception, which includes:
ADO.NET database connection resources (such as database, network sharing, message queue, etc.) are not available for business logic, including:
Verify the error in the stored procedure of business logic
Manage exceptions in data access logic components
Data Access Logic Components should disseminate exceptions and only package anomalous type only when the management of the client is easier to manage. Packing an exception is two major abnormal types (technical exceptions and business abnormalities) facilitates the exception processing structure and exception publishing logic of various possible calls.
Your application should publish exception information. Technology exceptions can be published to a log for monitoring tools (such as Microsoft Operations Manager) monitoring tools (such as Microsoft Operations Manager); publish business to a specific application log. Typically, it should be allowed to disseminate an exception from a data access logic component and allow an exception to be published by a calling program so that you understand an exceptional environment.
The following example illustrates these recommendations:
Public Class Customerdalc
{
Public Void UpdateCustomer (Dataset Acustomer)
{
Try
{
/ / Update the customer in the database ...
}
Catch (SQLException SE)
{
// Capture and package an exception, then re-issue
Throw New DataAccessException ("Database Not available", SE);
}
Finally
{
// Clear code
}
}
}
Manage exceptions in business entity components
Business entity components should disseminate abnormalities to the calling program. The business entity component can also produce an exception when the data required to perform a verification or when the calling program is attempting to perform an operation without providing the data.
The following example shows how business entity components produce exceptions. In this example, if the customer's name is not provided, the Update method will issue an exception: public class customer.
{
Public void update ()
{
// Check the user has provided the required data. Here is customer
// name
IF (firstname == "")
{
// Send a defined new application exception
Throw new myargumentexception ("You must provide the name.");
}
...
}
}
See Exception Management In .NET for more information on processing exceptions in .NET applications. The custom technology exception and custom business exception can be inherited from the ApplicationException class or the BaseApplicationException class supplied from Exception Management Application Block.
Authorization and security
This section explains how to apply security to data access logic components and business entity components. The .NET public language runtime use permission object implements its enforcement mechanism for managed code. There are three kinds of authority objects, each with specific uses:
Code Access Security. These permissions objects are used to prevent unauthorized use of resources and operations. Identity. These permission objects specify the identity characteristics necessary to run the assembly. Role-based security. These permission objects provide a mechanism to determine if the user (or user agent) has a specific identity identifier, or is a member of the specified role. The PrincipalPerMission object is the only role-based security permission object.
Managed code can use the Principal object (including reference to the Identity object) to determine the identity or role of the parties. Comparison of the concept of Identity objects and Principal objects with users, group accounts, etc. may be more easily understood. In the .NET Framework, the Identity object represents the user, and the role represents the member identity and security environment. Principal objects encapsulate identity objects and characters. The application in .NET Framework grants Principal object permissions based on the identity of the Principal object or the role member (the latter is more common).
For more information on the permissions and security in .NET, see Key Security Concepts.
Security suggestions in data access logic components
The design purpose of the data access logic component is to use for other application components, which is also your application code to access the last place before the call program can access the data.
Typically, data access logic components can depend on the security environment set by the calling program. However, in some cases the data access logic component must perform its own authorization check to determine if the parties are allowed to perform the requested operation. Authorization After authentication, and use the parties identifier to the role to determine the resources that the parties can access.
In the following cases, an authorization check should be performed at the data access logic component hierarchy:
Need to share data access logic components with incompletely trusting business, need to protect access to powerful features provided by data storage
After defining the Identity object and the Principal object, you can perform role-based security checks in three ways:
Use the PrincipalPerMission object to perform a mandatory security check. Use the PrincipalPerMissionAttribute property to perform an illustrative security check. Execute an explicit security check using the properties in the Principal object and the Isinrole method.
The following code example shows how to use PrincipalPerMissionAttribute to specify a role-based declarative security check for the method of data access logic component classes:
Using system.security.permissions;
Public Class Customerdalc
{
Public Customerdalc ()
{
}
// Use PrincipalPermissionattribute to request calls for this method
// With an identity named "Myuser" and belongs to the role "administrator".
[PrincipalPermissionatTribute (SecurityAction.Demand,
Name = "myuser", role = "administrator"]]
Public void deletecustomer (String Customerid)
{
/ / Remove customer code here
}
}
The following code shows how to create a Principal object with the required identity and role so that the deletecustomer method is called to the Customerdalc object:
Using system;
Using system.security.principal;
Using system.threading;
Public class mainclass
{
Public static int main (String [] ARGS)
{
Console.write ("User Name:");
String Username = console.readline ();
Console.write ("Password:");
String password = console.readline ();
IF (Password == "Password" && username == "myuser")
{
// Create a universal identity named "Myuser"
GenericIdentity myidentity = new genericidentity ("myuser");
// Creating a Role
String [] mystring = {"administrator", "user"};
// Create a general parties
GenericPrincipal myprincipal = new genericprincipal (MyIdentity,
Mystring);
// Set the current parties for this thread for role-based security
Thread.currentprincipal = myprincipal;
}
// Create a Customerdalc object and try to call its DeleteCustomer method.
// This step can only be successful when the identity identification and role of the parties are.
Customerdalc C = New Customerdalc ();
C. DeleteCustomer ("VINET");
}
}
Windows authentication
Ideally, use Windows authentication instead of SQL Server authentication when connecting to the database. However, you should use a service account and avoid analog connection to the database because it hinders the pool. The connection pool requires the same connection string; if you try to open the database with different connection strings, a separate connection pool is created, which will limit scalability.
For more information on Windows Authentication and Connection Pool, see "Managing Database Connections" in .NET Data Access Architecture Guide.
Security Communication Suggestions
To implement secure communication between calling applications and data access logic components, consider the following suggestions: If the data access logic component is called by the line of the various layers, the information exchange contains confidential information that needs to be protected, the distribution should be used. Security communication technology such as component object model (DCOM), Secure Socket Layer (SSL), Security Internet Protocol (IPSEC). If the data is encrypted in the database, the data access logic components are typically encrypted and decrypted. If the information exposure causes huge damage, it must be considered to protect the channels that communicate with the data access logic components.
Security suggestions in business entity components
If the business entity is implemented as a data structure (such as XML or Dataset), there is no need to implement security checks. However, if the business entity is implemented as a custom business entity component with CRUD operation, consider the following suggestions:
If you provide an entity to your incompletely trusted business procedure, an authorization check should be implemented in business entity components and data access logic components. However, if the inspections are implemented at these two levels, it may generate maintenance issues that maintain safety policies. Business entity components should not handle communication security or data encryption, these tasks should be left to the corresponding data access logic components.
deploy
This section provides some recommendations to help you determine how to deploy data access logical components and business entity components.
Deploy data access logic components
There are two ways to deploy data access logical components:
Deploy data access logic components along with your business process object. This deployment method has the best data transmission performance, and some additional technical advantages:
Transaction processing can seamless flow between business process objects and data access logic components. However, transaction processing cannot flow seamlessly across the remote channel. Under the remote scheme, you need to use DCOM to implement transaction. In addition, if the business process is separated from the data access logic component, the firewall port between the two physical layers is required to enable DTC communication. Deploy business process objects and data access logic components can reduce the number of transaction failed nodes. The security environment automatically flows between business process objects and data access logic components without setting parties. Deploy data access logic components along with the user interface code. Sometimes you need to use data access logic components from the UI component and the UI process component. To improve performance under Web schemes, you can deploy data access logic components along with the UI code; this deployment method can make the UI layer take advantage of the data reader stream to achieve optimal performance. However, you must keep in mind the following when using this deployment method:
A common reason for deploying data access logical components with the UI code is to prevent network access of the data source directly through the Web field. If your Web field is deployed in the DMZ environment, you must open the firewall port to access SQL Server. If you use COM transaction, you must also open other firewall ports for DTC communication. For more information, see .NET Data Access Architecture Guide.
Deploy business entity
Many of the different layers of the application use a business entity. Depending on the implementation of business entities, if your application spans each physical layer, you need to deploy business entities to multiple locations. The following is listed below to deploy business entities in different implementations:
Deploy as a business entity implemented as a type of DataSet. Type DataSet classes must be accessed by data access logical components and call applications. Therefore, it is recommended to define a type of DataSet class in a public program set to be deployed in multiple layers. Deploy as a business entity implemented as a custom business entity component. The custom entity class may need to be accessed by the data access logic component based on the method signed in the data access logic component. Follow the same recommendations as type DataSet, that is, define custom entity classes in a public complarge set to be deployed in multiple layers. Deploy as a business entity implemented as a general DataSet or XML string. GM DataSet and XML strings do not represent separate data types. There is no deployment issue in the business entity implemented in these two formats. appendix
How to Define Data Access Logical Components How to Use XML Represents Data Collection and Hierarchy How to Program the Application Style Table in .NET Application How to Create Type Dataset How to Define How to Represents Data in Business Entity Components and Hierarchies How to bind business entity components to user interface controls How to provide events in business entity components How to sequence the business entity component to XML format How to sequence the business entity component to SOAP format to binary format
How to define data access logical components
The following code example defines a class called Customerdalc, which is a data access logic component class for Customer business entities. The Customerdalc class implements CRUD operations for the Customer business entity and provides other methods to package business logic.
Public Class Customerdalc
{
PRIVATE STRING CONN_STRING
Public Customerdalc ()
{
/ / Get the connection string from a safe or encrypted location
/ / And assign it to conn_string
}
Public CustomerDataSet GetCustomer (String ID)
{
// Retrieve a type of DataSet that contains Customer data
}
Public String CreateCustomer (String Name)
String Address, String City, String State,
String Zip)
{
/ / Create one in the database based on the scalar parameters passing to this method
// new customer.
// Returns CustomerID from this method.
}
Public void UpdateCustom (CustomerDataSet UpdatedCustomer)
{
/ / According to the Customer data sent by the parameter as the type CustomerDataSet, update
// Database.
}
Public void deletecustomer (String ID)
{
/ / Delete customers with a specified ID
}
Public DataSet getCustomersWhopurchaseDProduct (int Productid)
{
// Use General DataSet to retrieve customers because this method
/ / Do not need to retrieve all information associated with customers
}
}
How to use XML to represent the collection and hierarchy of data
The following example shows how to represent a collection and hierarchy of data in an XML document. The XML document represents a order of the customer; note that the element
OrderDetail>
OrderDetail>
OrderDetail>
OrderDetails>
Order>
How to program the application style sheet in .NET application
To programmatically apply the style sheet in the .NET application, perform the following steps:
Import system.xml.xsl namespace, as shown in the following code. System.xml.xsl Namespace contains the XSLT conversion class in the .NET Framework class library. Using system.xml.xsl;
Create a XSLTransform object, as shown by the following code: xsltransform style, = new xsltransform ();
Load the desired style sheet to the XSLTransform object, as shown in the following code: Stylesheet.Load ("MyStylesheet.xsl);
The Transform method of the XSLTransform object is called, as shown in the following code. Call the Transform method to specify the name of the XML source document and the result document. Stylesheet.Transform (Sourcedoc, Resultdoc);
How to create a type of DataSet
You can use a type of DataSet to represent a business entity. There are many ways to create a type of DataSet:
Create an XSD architecture file from the Visual Studio .NET from the Microsoft Visual Studio ® .NET creation using the XSD Architecture Definition Tool (XSD.exe) from the .NET Framework Command Tips window.
Note: You can also program a type of DataSet that inherits and defines methods, properties, and nested classes from DataSet to indicate the structure of the DataSet. The easiest way is to create a type of DataSet using one of the following procedures, then use this type of DataSet class as the basis for your own type of DataSet classes in the future.
Create a type of DataSet using the data adapter
To create a type DataSet using the data adapter, perform the following steps:
Add a data adapter to your form or component in Visual Studio .NET. In the configuration wizard of the data adapter, specify the connection information of the data adapter. At the same time, according to the specific situation, specify the SQL string or stored procedure for the SELECT, INSERT, UPDATE, and DELETE commands of the data adapter. In the Component Designer, right-click on the data adapter object and click Generate Dataset. In the Generate Dataset dialog, click New, type the name of the new DataSet class, and then click OK. To confirm that the type of DataSet has been created, click Show All Files in the Solution Explorer. Expand the node of the XSD architecture file, confirm that there is a code file associated with the XSD schema. The code file defines a new type of DataSet class. Create a type of DataSet from the XSD architecture file
To create a type DataSet using Visual Studio .NET from the XSD schema file, perform the following steps:
In Visual Studio .NET, create a new project or open an existing project. Add an existing XSD architecture for the project or create a new XSD architecture in the Component Designer. In the Solution Explorer, double-click the XSD architecture file and view the XSD architecture in the Component Designer. Select the primary XSD architecture element in the Component Designer. In the Schema menu, click Generate Dataset. To confirm that the type of DataSet has been created, click Show All Files in the Solution Explorer. Expand the node of the XSD architecture file, confirm that there is a code file associated with the XSD schema. The code file defines a new type of DataSet class.
Create a type of DataSet with XSD.exe Define Tools (XSD.exe)
XML Architecture Definition Tools You can generate type DataSet from an XSD architecture file, an XDR architecture file, or an XML instance document. The following command uses XSDSChemafile.xsd XSD architecture files, generated in the Visual C # source file named xsdschemafile.cs in the current directory: A type of DataSet:
XSD / Dataset / Language: C # xsdschemafile.xsd
For more information, see Generating A Strongly Typed DataSet.
How to define business entity components
The following example shows how to define custom entity classes for the Product business entity:
Public Class Productentity
{
// Special field, used to save the status of the Product entity
Private int products;
Private string productname;
PRIVATE STRING QUANTINTYPERUNIT;
Private Decimal Unitprice;
Private short unitsinstock;
PRIVATE SHORT UNITSONORDER;
Private short reporderLevel;
// Public property, the state of the publication of the Product entity
Public int productID
{
Get {return products;} set {productId = value;
}
Public String ProductName
{
Get {return productname;}
Set {productName = value;
}
Public String QuantityPerUnit
{
Get {return quantityPerunit;}
Set {QuantityPerunit = value;
}
Public Decimal Unitprice
{
Get {return unitprice;}
Set {UNITprice = value;}
}
Public Short UnitsStock
{
Get {return unitsinstock;
Set {UnitsInstock = Value;}
}
Public Short Unitsonorder
{
Get {return unitsonorder;}
Set {unitsonorder = value;
}
Public Short ReorderLevelLevel
{
Get {return reorderLevel;}
Set {reorderLevel = Value;}
}
/ / Perform localization process method and attribute
Public Void IncreaseUnitpriceby (Decimal Amount)
{
UNITprice = Amount;
}
Public Short UnitsAboveReorderLevel
{
Get {Return (UnitsSinstock - REOREDERLEVEL);
}
Public String stockstatus
{
get
{
Return "stock:" unitsinstock ", order:" Unitsonorder;
}
}
}
How to represent a collection and hierarchy of data in business components
The following example shows how to define a custom entity class for the Order business entity. Each order contains many subscription items, which are saved in a DataSet of the Orderentity class.
Public class Orderentity
{
// Special field for saving order information
Private int orderId;
Private string customerid;
Private datetime orderdate;
Private datetime shippedddate;
// Special field for saving order details
Private Dataset OrderDetails;
// Public property, used to provide order information
Public int OrderID
{
Get {return ORDERID;
Set {ORDERID = VALUE;
}
Public String Customerid
{
Get {returnj
SET {Customerid = Value;
}
Public DateTime OrderDate
{
Get {return orderdate;}
Set {ORDERDATE = VALUE;
}
Public DateTime ShippedDate
{
Get {return.com
Set {shippeddate = value;
}
// Public property for providing order details
Public Dataset OrderDetails {
Get {returnraldetails;
Set {OrderDetails = Value;
}
// Additional method, used to simplify access to orders more information
Public Bool IsProductOrdered (int ProductID)
{
/ / Must define the primary key column in DataTable
DataRow Row = OrderDetails.tables [0] .rows.find (ProductID);
IF (row! = null)
Return True;
Else
Return False;
}
// Additional properties, used to simplify access to orders more information
Public int NumberoforderItems
{
get
{
Return OrderDetails.tables [0]. ROWS.COUNT;
}
}
}
For the ORDERENTITY class, please pay attention to the following points:
This class contains a dedicated field for saving information about orders. There is also a dedicated DataSet field for saving other details of the order. Data Access Logic Components will populate all of these fields when creating the OrdereEntity object. This class contains public properties for providing information about orders. There is also an attribute for providing the DataSet to enable calling applications to access order details. This class contains an additional method and an additional property that simplifies access to orders detail:
The IsProductOrdered method receives a productID parameter and returns a Boolean value to indicate whether the product appears in the order. The NumberOforderItems property indicates the number of order lines in the order.
How to bind business entity components to user interface controls
You can bind user interface controls to custom entities in a Windows Form and an ASP.NET application. There are two possible scenarios:
Bind a single business entity on the user interface control. The following code example shows how to get an ORDEREntity object from the OrderDalc object and bind it to the control of the Windows Form. When the user changes the values in these controls, the data in the foundation Orderentity object will also be automatically changed. // Create an ORDERDALC object.
ORDERDALC DALCORDER = New Orderdalc ();
// Use Dalcorder to get an Orderentity object for the order ID 10248.
// This code assumes that the ORDERDALC class has a method called getorder ().
// This method returns an Orderentity object for a particular order ID.
Orderentity Order = Dalcorder.GetORDER (10248);
// Bind the ORDERITY's OrderId property to the TextBox control.
TextBox1.Databindings.add ("text", order, "orderid");
// Bind the Orderentity's CustomerId property to another TextBox control.
CONTROL.
TextBox2.Databindings.add ("Text", Order, "Customerid");
// Bind the ORDERENTITY's OrderDate property to the DatePicker control.
DateTimePicker1.Databindings.add ("Value", Order, "ORDERDATE");
// Bind the outputity's ShippedDate property to another DatePicker control.
DateTimePicker2.dataBindings.add ("Value", ORDER, "ShippedDate); // Binds ORDERENTITY's OrderDetails Dataset to the DataGrid control.
// DataGrid displays the DataSet's DataRow with a line in the grid.
DataGrid1.datasource = Order.OrderDetails.tables [0] .defaultview;
When you are ready, you can pass the modified OrdereEntity object to ORDERDALC to save the data into the database, as shown in the following code. // Save the Orderentity object to the database via Dalcorder.
// This code assumes that the ORDERDALC class has a method called UPDATEORDER ().
/ / This method receives an Orderentity parameter and updates the corresponding item in the database.
Dalcorder.UpdateORDER (Order);
Complete the business entity to the DataGrid control. The following code example shows how to get an Orderentity object array from ORDERDALC and bind it to the DataGrid control of the Windows Form. DataGrid displays each array element (ie each ORDERENTITY object) with a line in the grid. // Create an ORDERDALC object.
ORDERDALC DALCORDER = New Orderdalc ();
// Use Dalcorder to get an array of ORDERENTITY objects of customer "Vinet".
// This code is assumed to have a named ORDERDALC class
GetOrDersForcustomer (),
// method, the method returns an array of Orderentity objects for a particular customer.
Orderentity [] Orderentities = Dalcorder.GetRDERSFORCUSTOMER ("VINET");
// bind the array to the DataGrid control.
DataGrid1.datasource = Orderentities;
After you are ready, you can pass the modified array to ORDERDALC to save the data into the database, as shown by Dalcorder: // Save the Orderentity object to the database via Dalcorder.
// This code assumes that the ORDERDALC class has a method called UpdateOrder (), which is obtained
// An ORDERENTITY object array and updates the corresponding item in the database.
Dalcorder.UpdateRDERS (Orderentities);
How to provide events in business entity components
Custom entities can generate events when they have modified business entity. These events can be used to get rich client user interface designs, as this makes it to refresh regardless of where the data is displayed. The following code example shows how to generate business entity related events in the Orderentity class:
/ / Define public event classes for all business entity events
Public Class EntityEventArgs: Eventargs
{
/ / Define event members to provide information about events
}
/ / Define a proxy for a signature for business entity related events
Public Delegate Void EntityEventHandler (Object Source, EntityEventArgs E);
// Define a custom entity class, which can generate events when the business entity status changes
Public class Orderentity
{
/ / Define "Before" event and "instance" event that changes the status of business entity
Public Event EntityEventHandler BeforeChange, AfterChange; // Special field, the status of the service entity
Private int orderId;
Private int Customerid;
Private datetime orderdate;
Private datetime shippedddate;
Private Dataset OrderDetails;
// Public property, used to provide a state of business entities
Public int OrderID
{
Get {return ORDERID;
set
{
BeforeChange (this, new entryEventArgs ()); // Generate "Before" event
ORDERID = VALUE;
Afterchange (this, new entryeventargs ()); // Generate an "instator" event
}
}
Public Int Customerid
{
Get {returnj
set
{
BeforeChange (this, new entryEventArgs ()); // Generate "Before" event
Customerid = Value;
Afterchange (this, new entryeventargs ()); // Generate an "instator" event
}
}
Public DateTime OrderDate
{
Get {return orderdate;}
set
{
BeforeChange (this, new entryEventArgs ()); // Generate "Before" event
ORDERDATE = VALUE;
Afterchange (this, new entryeventargs ()); // Generate an "instator" event
}
}
Public DateTime ShippedDate
{
Get {return.com
set
{
BeforeChange (this, new entryEventArgs ()); // Generate "Before" event
SHIPPEDDATE = VALUE;
Afterchange (this, new entryeventargs ()); // Generate an "instator" event
}
}
// Use more members when necessary ...
}
For the above code, please pay attention to the following points:
The EntityEvent class provides information about business entity related events. EntityEventHandler proxy specifies a signature for all business entity related events generated by custom entity classes. The agent signature follows the principles of the proposed .NET Framework event handler agent. See Event Usage Guidelines for the principles of the events defined and used in .NET. The Orderentity class defines two events called BeforeChange and AfterChange. The attribute settings in Orderentity generate a BeforeChange event before the business entity status changes, generate an AfterChange event after the business entity status changes.
How to sequence business components to XML format
This section discusses the following questions:
Using XMLSerializer Serialized Custom Entity Objects XML Services in XML Services in XML Web Services Control Series Default XML Format Control Serialized Custom Entity Objects XML Format
Use XMLSerializer serialized custom entity objects
The following code example shows how to use the XMLSerializer class to sequence the Orderentity object to XML format:
Using system.xml.serialization; // This namespace contains XMLSerializer class ...
// Create an XMLSerializer object to serialize the ORDERENTITY type object
XMLSerializer Serializer = New XMLSerializer (TypeOf (ORDERENTITY));
// Sequence the ORDERENTITY object to XML files called "myXmlorderentity.xml"
TextWriter Writer = New StreamWriter ("MyXMLORDERETITY.XML");
Serializer.Serialize (Writer, ORDER);
Writer.close ();
Serialized objects in XML Web Services
The following code example shows how to write XML Web Services that use custom entity objects:
Namespace MywebService
{
[WebService (Namespace = "URN: MyWebServiceNamespace")]]]
Public class Orderws: System.Web.Services.Webservice
{
[WebMethod]
Public Orderentity GetOrder (int OrderID)
{
// Create an ORDERDALC object
ORDERDALC DALCORDER = New Orderdalc ();
// Use Dalcorder to get the OrdereEntity object specified for the order ID.
// This code assumes that the ORDERDALC class has a method called Getorder,
/ / This method gets a order ID as a parameter and returns an Orderentity object.
// which contains all the data of the order.
Orderentity Order = Dalcorder.GetORDER (10248);
// Returns the ORDERENTITY object, which will automatically serialize.
Return ORDER;
}
[WebMethod]
Public void UpdateOrder (Orderentity Order)
{
// Create an ORDERDALC object.
ORDERDALC DALCORDER = New Orderdalc ();
// Save the data of the Orderentity object to the database using Dalcorder.
// This code assumes that the ORDERDALC class has a method called UpdateOrder.
// This method receives an ORDERENTITY object and saves the data into the database.
Dalcorder.UpdateORDER (Order);
}
For the above code, please pay attention to the following points:
The GetOrder method receives a order ID as a parameter and returns an OrdereEntity object containing the data of the order. The UpdateOrder method receives an ORDERENTITY object and saves the data of the object to the database. If the client application calls the GetOrder and UpdateOrder methods, the Orderentity object will call the automatic serialization to XML format for the method.
Default XML format for serialization custom entity objects
The following XML document shows the default XML sequence format of the Orderentity object:
XML Version = "1.0" encoding = "UTF-8"?>
XMLns: xsi = "http://www.w3.org/2001/xmlschema-instance"> Orderentity> The above document illustrates the default rules of XML serialization: The root element of the XML document is the same as class name orderentity. Each public property (and field) in the Orderentity object is serialized to an element having the same name. The ORDERDETAILS attribute in the Orderentity class is a DataSet, which provides built-in XML serialization support. The serialization results of OrderDetails DataSet are as follows: XMLns: XS = "http://www.w3.org/2001/xmlschema" XMLns: MSData = "URN: Schemas-Microsoft-COM: XML-MSDATA"> /> xs: sequence> xs: complexType> xs: element> xs: kice> xs: complexType> xs: element> xs: schema> Diffgr: Haschanges = "Inserted"> OrderDetails> Diffgr: Haschanges = "Inserted"> OrderDetails> Diffgr: Haschanges = "Inserted"> OrderDetails> NewDataSet> DIFFGR: DIFFGRAM> OrderDetails> For the serialization of DataSet, please pay attention to the following points: Control serialization custom entity object XML format You can use the .NET property in the custom entity class to control properties and field sequences to XML. Consider the following revised Orderentity class: [XMLROOT (ElementName = "Order", Namespace = "URN: MyNameSpace")]]] Public class Orderentity { [Xmlattribute (attributename = "id")]]]] Public int ORDERID {... get and set up code, the same ...} [XMlattribute (AttributeName = "CustID")]]] Public String Customerid {... Get and set up code, with the same ...} [xmlelement (elementname = "Ordered")] Public DateTime OrderDate {... get and set up code, the same ...} Public Dataset OrderDetails {... get and set up code, in the first ...} [XMLELEMENT (ElementName = "Shipped") Public DateTime shippedDate {... get and set up code, with the first ...} // Use more members when necessary ... } After sequence the ORDERENTITY object into XML, its format is as follows: XML Version = "1.0" encoding = "UTF-8"?> Custid = "Vinet" XMLns = "URN: MyNamespace" XMLns: xsd = "http://www.w3.org/2001/xmlschema" XMLns: xsi = "http://www.w3.org/2001/xmlschema-instance"> Order> For more information on how to use properties to control XML serialization, see Attributes That Control XML Serialization. How to sequence business entity components to SOAP format The following code example shows how to use the SOAPFormatter class to sequence the ORDEREntity object to the SOAP format. SOAP serialization (implicit) occurs when you use SOAP protocols or from XML Web Services, or when you use HTTP remote channels or from the Remoting server. In addition, you can specify SOAP formatting when using TCP remote channels. Using system.Runtime.Serialization.formatters.soap; // Used for SOAPFormatter class ... // Create a SOAPFORMATTER object to serialize the ORDERENTITY type object SOAPFORMATTER FORMATTER = New soapFormatter (); // Sequence the Orderentity object to the SOAP (XML) file named "MySoapordERENTITY.XML" FileStream Stream = file.create ("MySoaPordERENTITY.XML"); Formatter.Serialize (stream, order); stream.close (); To use SOAP serialization for custom entity components, you must use the serializable property to comment your entity class, as shown in the following code: [Serializable] Public class Orderentity { // member, the same If you want to customize the SOAP format generated during the serialization, the physical classes must implement the iSerializable interface. You must provide a getObjectData method for SOAPFormatter to call during serialization, and provide a special constructor for SOAPFormatter to recreate the object during the restore serialization process. The following code shows the use of the iSerializable interface, getObjectData method, and special constructor: use system.Runtime.Serialization; // Used for iSerializable interface and related types ... [Serializable] Public Class Orderentity: iSerializable { // Serialization function, called SOAPFORMATTER in the serialization process Void iSerializable.GetObjectData (SerializationInfo Info, StreamingContext CTXT) { / / Add each field to the SerializationInfo object Info.addvalue ("ORDERID", ORDERID; // Use more code if necessary ... } // Restore serialization function, called SOAPFormatter during the restore serialization process Public Orderentity (SerializationInfo Info, StreamingContext CTXT) { / / From the SerializationInfo object, it is still sequenced from each Orderentity field. ORDERID = (int) info.getValue ("ORDERID", TypeOf (int)); // Use more code if necessary ... } // Other members, the same ... } For more information on custom SOAP serialization, see Basic Serialization. How to serialize business components into binary format The following code example shows how to use the BinaryFormatter class to sequence the Orderentity object as a binary format. Binary serialization (implicit) occurs when you use TCP remote channels or from the Remoting server. In addition, in order to improve performance, you can specify binary formatting when using HTTP remote channels. Using system.runtime.serialization.formatters.binary; // Used for BinaryFormatter class ... // Create a BinaryFormatter object, used to serialize the ORDERENTITY type object BinaryFormatter Formatter = new binaryformatter (); // Sequence the ORDERENTITY object to binary files named "mybinaryorderentity.dat" FileStream Stream = file.create ("MyBinaryOrdereentity.dat); Formatter.Serialize (stream, order); stream.close (); To use binary serialization for custom entity objects, you must annotate your custom entity class using the serializable property. To customize the binary format generated during the serialization, the custom entity class must implement the iSerializable interface. The detailed code in both scenarios is the same as the SOAP serialized code. For more information on binary sequence, see binary serialization.