Grove Practice ORM
Glossary
Data Access Layer: Application code directly with the database based on logical hierarchical (Layer).
Business entity: The carrier of business data in the application, generally have DataSet, XML text, custom class. (details)
ORM: It is written by Object Relation Mapping. Popular lecture is to establish a map relationship between business ® body and relational database. (details)
Grove Develop Kit
Grove Develop Kit is a free data persistence layer and related tools developed by Chinese people, including Grove Develop Component and Grove Tool Kit: Grove Develop Component is a set of reusable development components based on .NET to provide developers A data persistence layer and provides a variety of ORM methods, and it also supports traditional ADO.NET-based database access. Grove Tool Kit is a Microsoft VS-based add-on. By using the Grove Tool Kit, developers can generate corresponding business entities directly from the database table in the VS environment, greatly improve development efficiency.
Applications
Description
This instance is intended to illustrate the application point of Grove, not provided. If you need all code, please download here.
Environment
1) Create a database called "Test" in the SQL Server database and establish the following two tables and correspondence (the type of business data used in this instance is very simple. In fact, Grove supports various data types):
Table Field Customer
Customerid Char (36) PKNAME â VARCHAR (50)
AddResse
Addressid Char (36) PKCUSTOMERID Char (36) Fklocation Varchar (200)
2) Create a TestGrove solution in VS, which protects the engineering DAL and DATAENTITY, the former is the data access layer, the latter is the business entity layer.
3) Open your Grove's operation interface through the menu "Tool-Grove Tool Kit". Configure the Grove database operating environment by clicking the "SET Connection String" button on the interface toolbar. After the configuration is complete, connect the database to address and Customer two tables. (The second button for the toolbar is used to set the database connection string, the first button is used to connect the database, the third button is used to create a business entity class)
Establish business entity
This example uses the self-description of the Self® righteous class as a business entity class. The so-called self-description is in the form of attribute in this class contains mapping relationships with the database. Individuals think this way is easy to understand and maintain.
4) Select the Address table in the Grove interface, click the code generation button to get the following code:
[DataTable ("address")]]]]
Public Class Address
{
String _addressid;
String_customerid;
String _location;
[Keyfield ("AddressID")]]]
Public String AddressID
{
Get {return this._addressid;
Set {this._addressid = value;
}
[ForeignKeyfield ("Customerid")]]
Public String Customerid
{
Get {return this._customerid;
Set {this._customerid = value;
}
[DataField ("location")]]
Public String Location
{
Get {return this._location;
Set {this._location = value;
}
}
Note: Grove looks the field as its own type when mapping the keyword field. This example does not use the self-increment ID to make a keyword, so you need to manually adjust. The code for the AddressID property is as follows:
[Keyfield ("addressid", keytype = uniqueidtype.OtherDefinition)]
Public String AddressID
{
Get {return this._addressid;
Set {this._addressid = value;
}
Use the same method to get a Customer business entity class, the code is as follows:
[DataTable ("Customer")]]]]
Public Class Customer PUBLIC CLASS CUSTOMER
{
String_customerid;
String _name;
[Keyfield ("Customerid", Keytype = UNIQUEIDTYPE.OrDefinition]
Public String Customerid
{
Get {return this._customerid;
Set {this._customerid = value;
}
[DataField ("name")]]]
Public String Name
{
Get {return this._name;}
Set {this._name = value;
}
}
5) Generate a strong type of business entity: GROVE temporarily does not support direct generation of business entity collection classes, so it is very simple in this part (you can get it with Copy Replace after writing), the code is as follows (to make the code simply only implementation Collection the most basic method):
Public Class AddressCollection: CollectionBase
{
Public Address this [int32 index]
{
set
{
THISLIST [INDEX] = VALUE;
}
get
{
Return (address) this.list [index];
}
}
Public INT32 Add (Address Value)
{
Return this.list.add (value);
}
}
Public Class Customercollection: CollectionBase
{
Public Customer this [int32 index]
{
set
{
THISLIST [INDEX] = VALUE;
}
get
{
Return (Customer) this.list [index];
}
}
Public Void Add (Customer Value)
{
This.List.Add (Value);
}
}
6) Modify the Customer class, add an Addresses property, access the property to get the Customer objects to all address. Add the following code:
Private addressCollection_addresses;
Public AddressCollection Addresses
{
get
{
IF (this._addresses == null) this._addresses = new addressCollection ();
Return this._addresses;
}
}
Establish a data access layer
7) ORM function: Grove provides ORM function The most important interface is IObjectOperator and IObjectQuery, the former provides INSERT, UPDATE, and DELETE functionality for business entities, which is primarily responsible for business entities. Grove does not provide the type of publication that directly implements the IObjectoperator interface, but we can get an instance of an IObjectOperator interface through the ObjectoperatorFactory factory class. code show as below:
Public Class Customerdb
{
// Insert a Customer object
Public Static Void Insert (Customer Customer)
{
IObjectoperator Objectoperator =
Objectoperatorfactory.getOpectoperator ();
Objectoperator.begintranscation (); // Start
Try
{
// Insert the property value of the Customer object and the database
Objectoperator.IsertObject (Customer);
// Plug the Address object corresponding to the Customer object
Objectoperator.InsertObjects (Customer.Addresses);
Objectoperator.commit (); // Submit a transaction
}
Catch
{
Objectoperator.rollback (); // rollback transaction
Throw;
}
Finally
{
Objectoperator.dispose ();
}
}
/ / Update a Customer object
Public Static Void Update (Customer Customer)
{
IObjectoperator Objectoperator =
Objectoperatorfactory.getOpectoperator ();
Objectoperator.begintranscation ();
Try
{
// Update Customer
Objectoperator.UpdateObject (Customer);
/ / Delete the Address corresponding to the Customer object
Objectoperator.removeChildObjects
Customer.customerid, TypeOf (address));
// Plug the Address object corresponding to the Customer object
Objectoperator.InsertObjects (Customer.Addresses);
Objectoperator.commit ();
}
Catch
{
Objectoperator.rollback ();
Throw;
}
Finally
{
Objectoperator.dispose ();
}
}
/ / Delete a Customer object
Public Static Void Remove (Customer Customer)
{
IObjectoperator Objectoperator =
Objectoperatorfactory.getOpectoperator ();
Objectoperator.begintranscation ();
Try
{
// Delete Customer objects
Objectoperator.removeObject (Customer);
/ / Delete the Address corresponding to the Customer object
Objectoperator.removeChildObjects (Customer.customerid, TypeOf (address);
Objectoperator.commit ();
}
Catch
{
Objectoperator.rollback ();
Throw;
}
Finally
{
Objectoperator.dispose ();
}
}
// Get a Customer collection through query conditions
Public Static Customercollection Readcustomers (String Filter)
{
IObjectoperator Objectoperator =
Objectoperatorfactory.getOpectoperator ();
IObjectQuery ObjectQuery =
Objectoperator.newquery (TypeOf (Customer));
ObjectQuery.filter = filter; // Set the query condition
CustomerCollection Customers = New CustomerCollection ();
Arraylist alcustomers;
Try
{
Alcustomers = ObjectQuery.execute (TypeOf (Customer);
Foreach (Object Ocustomer in Alcustomers)
{
Customer Customer = (CUSTOMER) Ocustom;
// Read the Address collection corresponding to Customer
ArrayList Aladdresses = new arraylist ();
Objectoperator.ReeveChildObjects
Customer.customerid, ALADDRESS, TYPEOF (AddRESS);
Foreach (Object Oaddress in Aladdresses)
{
Customer.Addresses.Add ((address) OADRESS;
}
Customers.Add (Customer);
}
}
Finally
{
Objectoperator.dispose ();
}
Return Customers;
}
}
The above code is relatively long, but the structure is relatively clear, the ideas are basically created Objectoperator -> Open Transaction -> Operation Database -> Release Objectoperator, the calling process uses try to capture exceptions. It is also worth mentioning that when Grove returns a data entity, it is saved in ArrayList, which requires a type conversion, then adds to a custom business entity collection.
8) Use SQL or stored procedures: Sometimes the above data access class does not fully meet our requirements, such as what we need to know the current database Customer, of course, this can be implemented through ADO.NET, but use Grove to implement Easy, the code is as follows (add to CustomerDB class):
// Read all Customer numbers
Public static int32 getcustomercount ()
{
IDBOPERATOR DBOPERATOR = DBOPERATORFAACTORY.GETDBOPERATOR (
Grove.appsettingmanager.GetAppSetting ("dbconnstring"));
Try
{
Return Convert.TOINT32 (
DBOPERATOR.EXECSCALAR ("Select Count (*) from Customer");
Finally
{
DBOPERATOR.DISPOSE ();
}
}
Comments and suggestions
The configuration information required for GROVE can only be set by the application configuration file, which cannot be directly set by the attribute, which is not conducive to unit testing.
Returns a data entity collection in ArrayList or DataSet, it is best to return a data entity collection in the form of CollectionBase, which facilitates the operational striker data entity collection.
Supports automatic generation of strong types of data entities.
Can generate a code file in the vs English environment.
Reference
GROVE site
Practice ORM, create Grove-based .NET applications