Construct my own ORM

GPS platform, site construction, software development, system operation and maintenance, to find a large forest network technology!
http://cnsendnet.taobao.com
from Sen Science and Technology official blog
http://www.cnsendblog.com/index.php/?p=495

 

By describing the previous two chapters, I believe many of my friends have to understand my following to discuss the implementation of the method to the ORM, and that is based on a custom Attribute to define O / R Mapping Rules, and then dynamically acquire this rule through reflection, dynamically constructed SQL statements.
Because this little thing (ORM) was born in Shenzhen, so I am still, she should have the name of Shenzhen, so I called her "MiniORM". I do not know how you think?
MiniORM uses ONE_INHERIT_TREE_ONE_CLASS (an inheritance tree corresponds to a table) structure, though this structure easily lead to data redundancy, but this structure is very simple. Also, a table considering only the present MiniORM a PK, FK a situation.

MiniORM following structure, to make it easier to understand and use, I use three categories:
. 1, OrmWriter: responsible entity object (such as the previous section, said Person) inserted into the database and the corresponding database record modifications.
2, OrmRemover: According to the entity responsible for the object, delete the specified records;
3, OrmReader: According to the entity responsible for the object, read the specified records;

Above is the three main classes of MiniORM. Here we detail in the foregoing description, step by step construction of her. We here or in front of that Person example.

The first chapter of this series, we know that there is not only an object inheritance, in particular, there are practical applications include the relationship, such as a Person contains two Hand (hand) class that contains a Head (head), etc., our Person in the database should have an ID, for more convenient use and discussion, this ID is an int and automatic growth type (ID INDENTITY (1,1)) in MiniORM in. These are the range of our MiniORM should consider.
We made changes to our Person:

  1. [DataObjectAttribute("Person")]
  2. public class Person
  3. {
  4. private int _ID;
  5. private string _Name;
  6. private int _Age;
  7. private string _Sex;
  8. private Head _Head;
  9. private Hand _LeftHand;
  10. private Hand _RightHand;
  11.  
  12. public int ID
  13. {
  14. get { return _ID; }
  15. set { _ID = value; }
  16. }
  17.  
  18. public Head Head
  19. {
  20. get { return _Head; }
  21. set { _Head = value; }
  22. }
  23.  
  24. public Hand LeftHand
  25. {
  26. get { return _LeftHand; }
  27. set { _LeftHand = value; }
  28. }
  29.  
  30. public Hand RightHand
  31. {
  32. get { return _RightHand; }
  33. set { _RightHand = value; }
  34. }
  35.  
  36. [DataFieldAttribute("name", "NvarChar")]
  37. public string Name
  38. {
  39. get { return this._Name; }
  40. set { this._Name = value; }
  41. }
  42.  
  43. [DataFieldAttribute("age", "int")]
  44. public int Age
  45. {
  46. get { return this._Age; }
  47. set { this._Age = value; }
  48. }
  49.  
  50. [DataFieldAttribute("sex", "NvarChar")]
  51. public string Sex
  52. {
  53. get { return this._Sex; }
  54. set { this._Sex = value; }
  55. }
  56. }

You may well find that a problem is in the Person our revised, increasing the LeftHand, RightHand and Head, but these three belong to class ah, how this can be saved to the database do? And using our previous DataFieldAttribute is no way to describe ah. It also adds a ID, and how to mark this automatic growth of PK int type it? Of course, here you will be able to find these problems it is quite good. If you will do it in front of people, it is estimated consideration is to modify our DataFieldAttribute it possible to distinguish these things. For example, in the DataFieldAttribute add a property which is an ID for distinguishing attribute, which is the object type (such as Hand) properties. This is of course good, but doing so leads to our code extremely ugly. The best way is to add an additional Attribute. Of course, I was to be more convenient to construct SQL statements, I do not very good.

1, PK indicate how the database table corresponding entity class and FK?
To make it easier to achieve, MiniORM flag of an entity class PK and FK are done in DataObjectAttribute in (in fact, the best solution is an additional one such PKAttribute and FKAttribute, but this is left to others to do it). Below, DataObjectAttribute first parameter corresponding database table, represented by the second parameter PK, the third parameter represents FK:

  1. [DataObjectAttribute("Person", "ID", "")]
  2. public class Person
  3. {
  4. ......
  5. }

2, how flag field is Indentity (automatic growth)?
Increased attributes in DataFieldAttribute, the field for a field mark whether the automatic growth. These are my personal lazy to do, which is the second parameter flag ID Identity type

  1. [DataFieldAttribute("ID", true)]
  2. public int ID
  3. {
  4. get { return _ID; }
  5. set { _ID = value; }
  6. }

3, how to mark the field is a class object (such as Person in Hand, of course, more complex objects, which may include a list of sub-objects)?
Because MiniORM provides is something of a similar framework, so it should not be limited by the entity class, so the class object field, we should be able to describe the assembly of this object is located, namespace, class name, created so that we can run the object.

  1. public class SubDataObjectAttribute : Attribute
  2. {
  3. private SubDataObjectFieldType _FieldType;
  4. private string _AssemblyName;
  5. private string _NamespaceName;
  6. private string _ClassName;
  7.  
  8. public SubDataObjectAttribute(SubDataObjectFieldType fieldtype, string assemblyname, string namespacename, string classname)
  9. {
  10. this._FieldType = fieldtype;
  11. this._AssemblyName = assemblyname;
  12. this._NamespaceName = namespacename;
  13. this._ClassName = classname;
  14. }
  15.  
  16. /// <summary>
  17. /// This record corresponding FieldType
  18. /// </summary>
  19. public SubDataObjectFieldType FieldType
  20. {
  21. get { return _FieldType; }
  22. }
  23.  
  24. /// <summary>
  25. /// This record corresponding AssemblyName
  26. /// </summary>
  27. public string AssemblyName
  28. {
  29. get { return _AssemblyName; }
  30. }
  31.  
  32. /// <summary>
  33. /// This record corresponding NamespaceName
  34. /// </summary>
  35. public string NamespaceName
  36. {
  37. get { return _NamespaceName; }
  38. }
  39.  
  40. /// <summary>
  41. /// This record corresponding ClassName
  42. /// </summary>
  43. public string ClassName
  44. {
  45. get { return _ClassName; }
  46. }
  47. }

SubDataObjectFieldType which is an enumerated type, because our sub-object may be a separate object such as Person.Head may also be a list (List). So I added this enumeration type, used to make signs.

  1. public enum SubDataObjectFieldType
  2. {
  3. Object,
  4. /// <summary>
  5. List Type /// This field belongs, to traverse directly
  6. /// </summary>
  7. List,
  8. }

Of course, here's a list of sub-objects may be ArrayList, HashTable, etc., you can do the appropriate changes according to their actual use to project type.

4, how to control a field can not be repeated in the table?
For example, we have to control Person.Name can not be repeated, if you add the time to find duplicate tips. Then we also be achieved by adding an Attribute form. Attribute this is very simple, there is no methods and properties.

  1. public class DataFieldNotDoubleAttribute : Attribute
  2. {
  3. }

5, how to do the transaction?
Each transaction is the underlying framework should take into account the problems in .NET we have two ways to handle transaction processing, is to use COM +, this is the best method, but the performance is quite lacking, the other thing that Configuring a lot of trouble when you database is installed on another too servers, often problems can not be used, I used to be this thing is frustrating enough to choke, so I just do not have him, but was introduced to grammar, by using TransactionScope can be a good use com + transactions provided by the code is quite simple, beautiful, but unfortunately ah! Angel face, devil's heart.

  1. public void function1()
  2. {
  3. using (System.Transactions.TransactionScope scope = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required))
  4. {
  5. function2 ();
  6. }
  7. }
  8.  
  9. public void function2()
  10. {
  11. using (System.Transactions.TransactionScope scope = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required))
  12. {
  13. //DoSomething();
  14. }
  15. }

Another method is to use SqlTransaction:

  1. using (SqlConnection conn = new SqlConnection(ConnectionStr))
  2. {
  3. conn.Open();
  4. SqlTransaction trans = conn.BeginTransaction();
  5. //DoSomething();
  6. trans.Commit();
  7. }

But unfortunately it can not be achieved in this way transaction nesting, so the transaction can only be achieved through the trans passed as an argument.

After a series of modifications above, our Person became what it was like?

  1. [DataObjectAttribute("Person", "ID", "")]
  2. public class Person
  3. {
  4. private int _ID;
  5. private string _Name;
  6. private int _Age;
  7. private string _Sex;
  8. private Head _Head;
  9. private Hand _LeftHand;
  10. private Hand _RightHand;
  11.  
  12. [DataFieldAttribute("ID", true)]
  13. public int ID
  14. {
  15. get { return _ID; }
  16. set { _ID = value; }
  17. }
  18.  
  19. [SubDataObjectAttribute(SubDataObjectFieldType.Object, "Person", "Person", "Head")]
  20. public Head Head
  21. {
  22. get { return _Head; }
  23. set { _Head = value; }
  24. }
  25.  
  26. [SubDataObjectAttribute(SubDataObjectFieldType.Object, "Person", "Person", "Hand")]
  27. public Hand LeftHand
  28. {
  29. get { return _LeftHand; }
  30. set { _LeftHand = value; }
  31. }
  32.  
  33. [SubDataObjectAttribute(SubDataObjectFieldType.Object, "Person", "Person", "Hand")]
  34. public Hand RightHand
  35. {
  36. get { return _RightHand; }
  37. set { _RightHand = value; }
  38. }
  39.  
  40. [DataFieldAttribute("name", "NvarChar")]
  41. public string Name
  42. {
  43. get { return this._Name; }
  44. set { this._Name = value; }
  45. }
  46.  
  47. [DataFieldAttribute("age", "int")]
  48. public int Age
  49. {
  50. get { return this._Age; }
  51. set { this._Age = value; }
  52. }
  53.  
  54. [DataFieldAttribute("sex", "NvarChar")]
  55. public string Sex
  56. {
  57. get { return this._Sex; }
  58. set { this._Sex = value; }
  59. }
  60. }
  61.  
  62.  

Of course, for such an entity class Person, we can write their own code generation tools to get, and then do minor modifications on it, this tool is simple, I will not discuss.
Well, on my MiniORM I discussed here, others see the code.

Although the ORM is a good thing, but there are also inadequate in many ways, first of all we can do is to pay a majority of database operations ORM do. In addition a small part of our own still need to write the SQL. Most of the separate single work can save us a lot of time (also known as the 20/80 principle, 80% of taught ORM to handle 20% of their own, of course, very good). In addition to processing by these same processes taught ORM, can avoid a lot of mistakes caused by negligence (such as accidentally put an Insert, Update, Delete statement made a mistake or something).
The main drawback of course is a performance problem, especially my MiniORM, all using reflection to get the mapping rules, leading to more drop in performance, but after we understand the method is very easy to pass dynamically generated code, dynamic compilation way reducing the performance loss of this part. Some additional part of the code somewhat cumbersome, particularly to determining whether such a code Indentity discharge DataFieldAttribute to process (as this kind can DataFieldNotDoubleAttribute a separate process) and the like.

 

GPS platform, site construction, software development, system operation and maintenance, to find a large forest network technology!
http://cnsendnet.taobao.com
from Sen Science and Technology official blog
http://www.cnsendblog.com/index.php/?p=495

Guess you like

Origin www.cnblogs.com/cnsend/p/12649838.html