. Net basics-update an object Using Generics and reflection (ADO. NET Entity Framework)

Source: Internet
Author: User

 

Since the launch of the ADO. NET Entity Framework, it has been popular, and it encapsulates a large numberCodeThe generated tool. You only need to establish the relationship between objects. The system will automatically add, delete, Createobject, attach, tolist ...... and so on. These methods basically include basic methods such as getting, deleting, and inserting, which are very convenient to use. Only in object update, because LINQ is oriented to generic object t, the update method of each object must be automatically edited by the user. As you can see, the following uses the reflection method to create an update tool that can update any or multiple associated entities in objectcontext.

 

 1. Introduction to reflection

Reflection isProgramThrough reflection, the internal information of *. EXE or *. dll can be obtained. Reflection allows you to view the interfaces, classes, methods, fields, attributes, and features of an assembly. The system. Reflection namespace contains multiple common anti-injection classes. The following table lists several frequently-used classes. (For more information, see"The mysteries of reflection")

Type Function
Assembly This class can be used to load and manipulate an assembly and obtain internal information of the Assembly.
Eventinfo This class stores the specified event information
Fieldinfo This class stores the given field information
Methodinfo This class saves the given method information
Memberinfo This class is a base class that defines multiple public behaviors of eventinfo, fieldinfo, methodinfo, and propertyinfo.
Module This class allows you to access the given modules in multiple assemblies.
Parameterinfo This class saves the given parameter information
Propertyinfo This class saves the given property information

 

 

Ii. Relationship between entities and context

Each object value is included in the Context. When you recycle objects from the client, you can compare the updated object version with the object in the context and apply the appropriate changes. It is worth noting that the context requires the key to locate the object and assign values to each attribute one by one. If you want to assign values directly to an object, the key will change and the system will not be able to find the object from the context.

 

 

Iii. Development Instance

When creating a relationship diagram for a project, multiple entities are connected. When updating an object, you must update the navigation attributes together, which makes the update method more complicated. For example, in the order management project, when updating the order, the orderitem object corresponding to the order must be synchronously updated. To simplify the code, we use the reflection principle to create a specific class updatehelp. This class can be used to update multiple relational objects in objectcontext.

The principle is that the system uses the getintrinsicobj (entityobject) method to obtain the corresponding object (intrinsic) in the context based on the key of the input object (OBJ), and then uses the updateintrinsticobj (object) method, use propertyinfo to traverse every attribute of an object and assign each attribute of the input object (OBJ) to the context object (intrinsic ). The most special thing is that recursion is used when a navigation attribute is encountered.AlgorithmThe updateintrinsticobj (object) method is repeatedly called to assign a value to the navigation attribute. When a one-to-many or many-to-many relationship is encountered, the navigation property will be a list <t> object. In the method, clonenavigationproperty is assigned a value to a single object, the clonenavigationpropertyentitycollection method assigns values to multiple objects.

 Public   Class Updatehelp: idisposable
{
// Record object classes that have already been copied to avoid repeated loading
Private Ilist <type> listtype = New List <type> ();
Private Businesscontext _ context;

Public Updatehelp (businesscontext context)
{
_ Context = context;
}

Public Void Dispose ()
{
_ Context. Dispose ();
}

// Update common attributes
Private Void Cloneproperty (propertyinfo, Object Intrinsicobj, Object Newobj)
{
VaR Data = propertyinfo. getvalue (newobj, Null );
Propertyinfo. setvalue (intrinsicobj, data, Null );
}

// Update common navigation attributes
Private Void Clonenavigationproperty (propertyinfo, Object Intrinsicobj, Object Newobj)
{
VaR Data = propertyinfo. getvalue (newobj, Null );
Object Dataclone = updateintrinsticobj (data );
Propertyinfo. setvalue (intrinsicobj, dataclone, Null );
}

// The returned value is the navigation attribute of the Set entitycollection <tentity>.
Private Void Clonenavigationpropertyentitycollection (propertyinfo, Object Intrinsicobj, Object Newobj)
{
// Obtain the object set in newobj.
Ienumerable < Object > Newdata = propertyinfo. getvalue (newobj,Null ) As Ienumerable < Object >;
// Get the set of original objects matching in the context
VaR Intrinsicdata = propertyinfo. getvalue (intrinsicobj, Null );
// Use the extended method of entitycollection <tentity> class to add a new object to the original collection.
VaR Addmethod = intrinsicdata. GetType (). getmethod (" Add " );
Foreach ( Object OBJ In Newdata)
{
Object objclone = updateintrinsticobj (OBJ );
Addmethod. Invoke (intrinsicdata, New Object [] {Objclone });
}
}

// Get the original object to be updated in the context
Private Object Getintrinsicobj (entityobject entity)
{
Object intrinsicobj;
// Determines whether the object is an existing value or a new value based on the entitykey of the input object.
// If the existing value is used, the corresponding value is obtained from the context. If the new value is used, a new object is generated.
If (Entity. entitykey. entitykeyvalues! = Null )
Intrinsicobj = _ context. getobjectbykey (entity. entitykey );
Else
Intrinsicobj = activator. createinstance (entity. GetType ());

Return Intrinsicobj;
}

// Update the original object in the context. The returned value is the updated original object.
Public Object Updateintrinsticobj (Object OBJ)
{
// Record object classes that have already been copied to avoid repeated loading
Listtype. Add (obj. GetType ());
// Obtain the original object in the context
Object intrinsicobj = getintrinsicobj (OBJ As Entityobject );
// Update each attribute of the original object
// Set each attribute of the original object intrinsicobj to be equal to that of the OBJ object.
Foreach (Propertyinfo In OBJ. GetType (). getproperties ())
{
// If the listtype contains some types, it indicates that the object class has been updated.
If (! Listtype. Contains (propertyinfo. propertytype) & propertyinfo. canwrite
& Amp; propertyinfo. Name! = " Entitykey " & Amp; propertyinfo. propertytype. Name! = " Entityreference '1 " )
{
// If it is a navigation property, you need to use this method to update
If (Propertyinfo. getcustomattributes ( Typeof (Edmrelationshipnavigationpropertyattribute ), False ). Count ()! = 0 )
{
// This method is used if the return value of the navigation property is a set.
If (Propertyinfo. propertytype. Name = " Entitycollection '1 " )
Clonenavigationpropertyentitycollection (propertyinfo, intrinsicobj, OBJ );
Else // If the navigation property is a common object, use the following method:
Clonenavigationproperty (propertyinfo, intrinsicobj, OBJ );
}
Else // If the attribute is normal, use the following method:
Cloneproperty (propertyinfo, intrinsicobj, OBJ );
}
}
Return Intrinsicobj;
}
}

After the update operation is completed, you can use the linghelp class to complete most data processing problems. You can establish a main test.

     Public   Class Linqhelp: idisposable
{
Private Businesscontext _ context;
Private Updatehelp _ updatehelp;

Public Linqhelp ()
{
_ Context = New Businesscontext ();
_ Updatehelp = New Updatehelp (_ context );
}

Public Linqhelp (businesscontext context)
{
_ Context = context;
_ Updatehelp = New Updatehelp (context );
}

Public Void Dispose ()
{
_ Context. Dispose ();
}

Public Int Add <t> (T entity) Where T: entityobject
{
Int N =- 1 ;
Transaction = Transaction. Current;
Try
{
_ Context. addobject (entity. GetType (). Name, entity );
N = _ context. savechanges ();
}
Catch (Exception ex)
{
Business. Common. exceptionmanager. dataexception. dealwith (Ex );
Transaction. rollback ();
}
Return N;
}

Public Int Update <t> ( Ref T entity) Where T: entityobject
{
Int N =- 1 ;
Transaction = Transaction. Current;
Try
{
Entityobject returnobj = This . _ Updatehelp. updateintrinsticobj (entity) As Entityobject;
N = _ context. savechanges ();
Entity = _ context. getobjectbykey (entity. entitykey) As T;
}
Catch (Exception ex)
{
Business. Common. exceptionmanager. dataexception. dealwith (Ex );
Transaction. rollback ();
}
Return N;
}

Public List <t> getlist <t> ( String Name) Where T: entityobject
{......}
........
}

Public Class Orderrepository
{
Private Linqhelp _ linqhelp;

Public Orderrepository ()
{
_ Linqhelp = New Linqhelp ();
}

Public Int Addorder (order)
{..........}

..............

Public Int Updateorder (order)
{
Return _ Linqhelp. Update <order> ( Ref Order );
}
}
  Public   Class Personrepository
{......}

Class Program
{
Static Void Main ( String [] ARGs)
{
Test1 ();
Console. readkey ();
}

Public Static Void Test1 ()
{
Using (Businesscontext context = New Businesscontext ())
{
Context. contextoptions. lazyloadingenabled = True ;
VaR Order = context. Order. First ();
Order. Person. Address =" No. 1 Beijing Road " ;
Orderrepository = New Orderrepository ();
Orderrepository. updateorder (order );
}
}

Public static void Test2 ()
{
Using (businesscontext context = new businesscontext ())
{
Person = context. Person. First ();
Order order = New Order ();
Order. ordernumber = "2a34313344 ";
Orderitem = new orderitem ();
Orderitem. goods= "555 ";
Orderitem. Count = 8;
Orderitem. Price = 2.5;
Order. orderitem. Add (orderitem );
Person. Order. Add (order );

Personrepository = new personrepository ();
Personrepository. updateperson (person );
Console. Write (person. Order. First (). ID + person. Order. First (). orderitem. First (). Id );
}
}
}

 

Iv. performance problems

The excessive use of reflection will degrade the system performance, so pay attention to the scope of use of this update method. Generally, this reflection update is only used in small projects. If it is used in large and medium-sized projects, it will bear the performance cost. Due to limited time and no tests, please comment on any shortcomings.

If you are interested in. NET development, join the blog forum discussion group.". Net advanced programming"Join us!

 

. Net Basics

Operate TCP/IP sockets in asynchronous mode -- implement simple chat rooms in asynchronous mode Reasonably use the ". Net Extension Method" to simplify the code (example: null value judgment, using the extension method to implement the LINQ operator foreach) Division class and division method The mysteries of reflection Update an object Using Generics and reflection (ADO. NET Entity Framework)

Author: wind dust prodigal son

Http://www.cnblogs.com/leslies2/archive/2011/11/24/2257572.html

Original Works. Indicate the author and source when reprinting.

 

 

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.