In Part 1: Generic Data Access Layer using ADO.NET Entity Framework of this series, I demonstrated how to generate a data model using the ADO.NET Entity Framework.
In this article, we will take a deeper look at what the ADO.NET Entity Framework has provided us and how we can modify it to achieve a Generic Data Access Layer.
The Entity Framework creates a ObjectContext class for us. This class provides us access to all the tables in the database and hence provides access to the data.
The following code snippet is an example of how a DataContext class is created by the ADO.NET Entity Framework.
  1. public partial class PublishingCompanyEntities : ObjectContext
  2. {
  3. }
If you dig deeper into this class, you will see definitions like the following:
Generic Dal using WCF
As shown in the screenshot above, the ObjectContext provides us with methods which help us access the Database.
Now let's take a look at the entities. The Entity Framework creates partial classes for each of the tables in the data model. These partial classes extend the EntityObject class as shown below.
Generic Dal using WCF
Below is the code for the Author entity.
  1. [EdmEntityTypeAttribute(NamespaceName = "PublishingCompanyModel", Name = "Author")]
  2. [Serializable()]
  3. [DataContractAttribute(IsReference=true)]
  4. public partial class Author : EntityObject
  5. {
  6. #region Factory Method
  7. /// <summary>
  8. /// Create a new Author object.
  9. /// </summary>
  10. /// <param name="authorID">Initial value of the AuthorID property.</param>
  11. public static Author CreateAuthor(global::System.Int32 authorID)
  12. {
  13. Author author = new Author();
  14. author.AuthorID = authorID;
  15. return author;
  16. }
  17. #endregion
  18. #region Primitive Properties
  19. /// <summary>
  20. /// No Metadata Documentation available.
  21. /// </summary>
  22. [EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
  23. [DataMemberAttribute()]
  24. public global::System.Int32 AuthorID
  25. {
  26. get
  27. {
  28. return _AuthorID;
  29. }
  30. set
  31. {
  32. if (_AuthorID != value)
  33. {
  34. OnAuthorIDChanging(value);
  35. ReportPropertyChanging("AuthorID");
  36. _AuthorID = StructuralObject.SetValidValue(value);
  37. ReportPropertyChanged("AuthorID");
  38. OnAuthorIDChanged();
  39. }
  40. }
  41. }
  42. private global::System.Int32 _AuthorID;
  43. partial void OnAuthorIDChanging(global::System.Int32 value);
  44. partial void OnAuthorIDChanged();
  45. /// <summary>
  46. /// No Metadata Documentation available.
  47. /// </summary>
  48. [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=true)]
  49. [DataMemberAttribute()]
  50. public global::System.String FirstName
  51. {
  52. get
  53. {
  54. return _FirstName;
  55. }
  56. set
  57. {
  58. OnFirstNameChanging(value);
  59. ReportPropertyChanging("FirstName");
  60. _FirstName = StructuralObject.SetValidValue(value, true);
  61. ReportPropertyChanged("FirstName");
  62. OnFirstNameChanged();
  63. }
  64. }
  65. private global::System.String _FirstName;
  66. partial void OnFirstNameChanging(global::System.String value);
  67. partial void OnFirstNameChanged();
  68. /// <summary>
  69. /// No Metadata Documentation available.
  70. /// </summary>
  71. [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=true)]
  72. [DataMemberAttribute()]
  73. public global::System.String LastName
  74. {
  75. get
  76. {
  77. return _LastName;
  78. }
  79. set
  80. {
  81. OnLastNameChanging(value);
  82. ReportPropertyChanging("LastName");
  83. _LastName = StructuralObject.SetValidValue(value, true);
  84. ReportPropertyChanged("LastName");
  85. OnLastNameChanged();
  86. }
  87. }
  88. private global::System.String _LastName;
  89. partial void OnLastNameChanging(global::System.String value);
  90. partial void OnLastNameChanged();
  91. #endregion
  92. #region Navigation Properties
  93. /// <summary>
  94. /// No Metadata Documentation available.
  95. /// </summary>
  96. [XmlIgnoreAttribute()]
  97. [SoapIgnoreAttribute()]
  98. [DataMemberAttribute()]
  99. [EdmRelationshipNavigationPropertyAttribute("PublishingCompanyModel", "FK_Article_Author", "Article")]
  100. public EntityCollection<Article> Articles
  101. {
  102. get
  103. {
  104. return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedCollection<Article>("PublishingCompanyModel.FK_Article_Author", "Article");
  105. }
  106. set
  107. {
  108. if ((value != null))
  109. {
  110. ((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedCollection<Article>("PublishingCompanyModel.FK_Article_Author", "Article", value);
  111. }
  112. }
  113. }
  114. /// <summary>
  115. /// No Metadata Documentation available.
  116. /// </summary>
  117. [XmlIgnoreAttribute()]
  118. [SoapIgnoreAttribute()]
  119. [DataMemberAttribute()]
  120. [EdmRelationshipNavigationPropertyAttribute("PublishingCompanyModel", "FK_Payroll_Author", "Payroll")]
  121. public EntityCollection<Payroll> Payrolls
  122. {
  123. get
  124. {
  125. return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedCollection<Payroll>("PublishingCompanyModel.FK_Payroll_Author", "Payroll");
  126. }
  127. set
  128. {
  129. if ((value != null))
  130. {
  131. ((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedCollection<Payroll>("PublishingCompanyModel.FK_Payroll_Author", "Payroll", value);
  132. }
  133. }
  134. }
  135. #endregion
  136. }
Each partial class is decorated with attributes.
Let's take a look at these attributes.
EdmEntityTypeAttribute
Attribute that indicates that the class represents an entity type. Without this attribute on top of the partial class, the class will not be recognised as an Entity Type.
GenWCF3.gif
Example of using this attribute is shown below:
[EdmEntityTypeAttribute(NamespaceName="PublishingCompanyModel", Name="Author")]
Serializable
Indicates that a class can be serialized. Apply the SerializableAttribute attribute to a type to indicate that instances of this type can be serialized. The common language runtime throws SerializationException if any type in the graph of objects being serialized does not have the SerializableAttribute attribute applied.
Example is given below :
[Serializable()]
DataContractAttribute
Specifies that the type defines or implements a data contract and is serializable by a serializer, such as the DataContractSerializer. To make their type serializable, type authors must define a data contract for their type.
Example is given below :
[DataContractAttribute(IsReference=true)]
Summary
In this part of this series, we saw how the data model and data entities are defined and created by the ADO.NET Data Entity Framework. Without understanding these internals, it is not possible to create a generic data access layer.
Next >> Generic Data Access Layer for WCF : Part 3