Four ORM Implementation Solutions

Source: Internet
Author: User

As indicated by the ORM name, the key to implementing the ORM is to resolve the ing between "Object-relation". For example, how to convert a datarow into an entity object, and how to map an operation on an entity object to an idbcommand. Take datarabbit as an example,In datarabbit, use the iormapping interface to abstract these mappings:

Public   Interface  Iormapping < Tentity >
{
Tentity getentityfrom (DatarowRow, Bool Withblob );

///   <Summary>
/// Fillparametervalue uses the entity content to fill in the parameter values of each idbdataparameter in the command.
///   </Summary>
Void Fillparametervalue (IdbcommandCommand, tentity entity );
}

There are at least four solutions for implementing the iormapping interface. Let's take the getentityfrom method as an example to describe these four solutions. This method is to convert a datarow into an entity object.

1.CodeGenerator

Currently, many code generators can directly generate the Dal layer that implements the ORM function. The principle behind this layer is to follow the outline of the data table (such as the columns and types of each column) to generate the corresponding class that implements the iormapping interface. The Code Generator completes these tasks before compilation.

2. Reflection

Convert a datarow to an entity object. If the granularity is finer, we need to solve how to assign the values of a column of datarow to the corresponding attributes of the entity object, we can use reflection to assign values to the attributes of the entity object at runtime, for example:

Entitytype. invokemember (columnname,Bindingflags. Public |  Bindingflags. Ignorecase |
Bindingflags. Instance |  Bindingflags. Setproperty, Null , Entity, row [columnname]);

The meaning of this line of code isRowThe value of the columnname column in is assignedEntityThe object's columnname attribute.

3. emit

At runtime, We can dynamically launch corresponding iormapping interface types based on each entity type. After these dynamic types are successfully launched, they can be instantiated and used. For example, we want to launch the code that implements the getentityfrom method:

Private   Void Emitgetentityfropolichod (TypebuilderTypebuilder,MethodinfoBasemethod,TypeEntitytype,DataschemaDataschema)
{
MethodbuilderMethodbuilder = Typebuilder. definemethod ( " Getentityfrom " , Basemethod. Attributes &   ~ Methodattributes. Abstract, basemethod. callingconvention, basemethod. returntype, emithelper. getparameterstype (basemethod ));
Ilgenerator = Methodbuilder. getilgenerator ();
Label retlabel = Ilgenerator. definelabel ();
Ilgenerator. declarelocal (entitytype ); // Member member = NULL;
Ilgenerator. emit (Opcodes. Nop );
Ilgenerator. emit (Opcodes. newobj, entitytype. getconstructor ( New Type [] {});
Ilgenerator. emit (Opcodes. stloc_0 ); // Member = new member ();

Ilist < Propertyinfo > Bloblist =   New List < Propertyinfo > ();
# Region Assign values to non-blob attributes
Foreach (Propertyinfo Property In Entitytype. getproperties ())
{
Columnschema = Dataschema. getcolumnschema (property. Name );
If (Columnschema =   Null )
{
Continue ;
}

If (Property. propertytype =   Typeof ( Byte []) && ( ! Columnschema. istimestamp ))
{
Bloblist. Add (property );
Continue ;
}

emitsetproperty (entitytype, ilgenerator, property);
}< br> # endregion

If(Bloblist. Count> 0)
{
Ilgenerator. emit (Opcodes. ldarg_2 );
Ilgenerator. emit (Opcodes. brfalse, retlabel );

# Region Assign values to blob attributes
Foreach (PropertyinfoProperty In Bloblist)
{
Emitsetproperty (entitytype, ilgenerator, property );
}
# Endregion
}

Ilgenerator. marklabel (retlabel );
Ilgenerator. emit (Opcodes. Nop );
Ilgenerator. emit (Opcodes. Ldloc_0 );
Ilgenerator. emit (Opcodes. Ret );

Typebuilder. definemethodoverride (methodbuilder, basemethod );//Define method overload
}

 

4. Use the Lamda expression

If it is in. net3.5, we can use a dynamically generated Lamda expression to assign values to the entity object attribute. The key point is how to generate a dynamic delegate for assigning values. For example:

 

  Private  Action < Tentity, Object > Createfunctionofsetproperty < Tentity > (MethodinfoSetpropertymethod,TypeColumntype)
{
ParameterexpressionParamentityobj =  Expression. Parameter ( Typeof (Tentity ), " Entity " );
ParameterexpressionParamproval =  Expression. Parameter ( Typeof ( Object ), " Propertyval " );
UnaryexpressionParamproval2 =  Expression. Convert (paramproval, columntype );
MethodcallexpressionBody =  Expression. Call (paramentityobj, setpropertymethod, paramproval2 );
Expression < Action < Tentity, Object > Setpropertyexpression =  Expression. Lambda < Action < Tentity, Object > (Body, paramentityobj, paramproval );

Action<Tentity,Object>Setpropertyaction=Setpropertyexpression.Compile();

Return(Entity, propertyval)=>{Setpropertyaction (entity, propertyval );};
}

This method returns a delegate. The returned delegate receives two parameters: entity object and the attribute value to be assigned. by calling this delegate, you can assign a value to an attribute of the entity object.

 

Now, we have briefly introduced the four solutions. Let's make a comparison.

(1) Except for the first scheme completed during the compilation period, the last three schemes are completed during the runtime.

(2) The first solution has the highest efficiency, but the most manual operations are required (for example, the Dal layer needs to be regenerated every time the table structure is modified ). The efficiency of the second solution is the lowest, and reflection results in a very high loss of efficiency. The efficiency of the last two solutions is good (almost close to that of the first solution ).

(3) The implementation of the emit solution should be the most difficult, followed by the Lamda expression solution.

(4) Lamda expressions can be used only on. net3.5 and later platforms.

Datarabbit 3. X and earlier versions use the emit solution, and later versions 4.0 and later support both the emit solution and the Lamda expression solution (the default is the emit solution, you can modify the configuration option to use the Lamda expression scheme ).

 

 

 

 

 

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.