Table of Contents [Hide/Show] Entity Layer What is an Entity? A bit of history: The Entity Relationship Model What's your definition of an entity? EntityBase What is Entity State? Entity LifeCycle Base State Behavior Interface Implementations What about generated views? Are they entities? Entity Validation Rule Engine Example of Auto-Generated Rules That's great, but, how do I add my own rules? So, how do I validate and see the error message? Using Collections in .netTiers, TList & VList: Entity Management Framework: EntityFactoryBase EntityCache IEntityCacheItem EntityLocator EntityManager Edit Entity Layer Edit What is an Entity? An Entity is not a regular .net type, it is a significant type that holds an intrinsic meaning that is essential in your application. Entities can be real or conceptual and in business applications, which .netTiers is tailored to, holds a special meaning to the data. For example: an Employee, an Order and OrderDetail are all entities. Entities are malleable and have a lifecycle, and their types must take extra special checks and balances to ensure the integrity of the entity. Edit A bit of history: The Entity Relationship Model The entity first came to be known as the Entity Relation model, ERM. You can read the white paper that pretty much coined the term Entity and the entity life cycle. The Entity Relationship Model - Toward A Unified View of Data - By Dr. Peter Chen. This is significant because it was the first time there was a segregration in the way we made representations in a program from our data. These representations allow to focus on creating a rich programmer experience with these valuable representations that we Edit What's your definition of an entity? .netTiers uses the notion of the entity along with the TableModule & Data Transfer Object (DTO) Patterns in order to expose your database as entities. Meaning, for every table in your database, an entity will be generated for that table. The DTO allows you to pass the lightweight entities through the many tiers while still maintaining the loosely coupled open ended architecture of the Entity Layer, since it doesn't depend on any DataProvider. .netTiers will also attempt to discover all of the relationships that your table has with other tables in the database and will create child properties of those relationships. This will build out your entire entity domain. Currently the relationship types supported are one to one, one to many, and and many to many relationships. These relationships make it easy for you to intuitively work with your entities and now have a logical object graph. There are several ways to create a certain relationship, but we'll discuss the rules in the Database Model section. Example: Customer Entity /**////An example object graph of a customer entity looks like this. /// Customer Parent /// Order 1:1 /// OrderDetails //1:M /// ProductCollection //1:M /// CustomerDemographics //1:M /// CustomerDemographicsCollection_From_CustomerCustomerDemo //M:M Edit EntityBase The entities all inherit from two parent classes, the user class called EntityBase.cs which inherits from EntityBaseCore.generated.cs, the generated class. As mentioned earlier, every .generated class will be generated over and over again, do not modify these classes as your work will be lost when you regenerate your code. These base classes implement the the base behavior across all entities. The EntityBase class provides you with exlusive access to modify the behavior across all entities. You can override our default implementation and these changes will not get overwritten. This is a way for you to make changes and extend the behavior while at the same time, safeguarding your work. EntityBase The EntityBase classes provide behavior to manage state using the EntityState property. Edit What is Entity State? Entity State provides a way to track the current status of an entity in it's entity lifecycle, which differs from the CLR object lifecycle. There are 4 main EntityStates, found in the EntityState enumeration, Unchanged, Added, Changed, and Deleted. You do not have to manually keep track of state, when you modify a property, or create a new entity, or read an entity from the database .netTiers will automatically change the state and keep track for you. 1/**//**//**////<summary> 2/**//// List of possible state for an entity. 3/**////</summary> 4publicenum EntityState 5 ......{ 6/**//**//**////<summary> 7/**//// Entity is read in from the database, unchanged 8/**////</summary> 9 Unchanged=0, 10 11/**//**//**////<summary> 12/**//// Entity is new and not yet in the database 13/**////</summary> 14 Added=1, 15 16/**//**//**////<summary> 17/**//// Entity has been modified 18/**////</summary> 19 Changed=2, 20 21/**//**//**////<summary> 22/**//// Entity has been deleted 23/**////</summary> 24 Deleted=3 25 } Edit Entity LifeCycle Assuming you have no data in your database, the very first thing you will dois add data to the database. In order to dothis, you will have to create a new entity. Let's use the Customer entity that we've generated from the Northwind database, and create a new Customers entity and walk through the different states of the entity, which as mentioned earlier is different than the object lifecycle. 1/**//**//**////STAGE 1: Added 2/**////Create a new entity, whose EntityState is EntityState.Added 3 Customers customer =new Customers(); 4 customer.Address ="102 West Main Street"; 5 customer.City ="Atlantis"; 6 customer.Region ="Sea"; 7 customer.Phone ="230-555-0909"; 8 Response.Write(customer.EntityState); // EntityState.Added; 9 10/**//**//**////Persist 11 DataRepository.CustomersProvider.Save(customer); 12 13 14/**//**//**////STAGE 2: Unchanged 15/**//// The EntityState has been set to EntityState.Unchanged 16/**////Once we persist the entity, it will refresh the entity from the database 17/**////If there is an identity column in your table that the entity represents 18/**//// then the new identity of the inserted value is returned as well. 19 Response.Write(customer.CustomerID); 20 Response.Write(customer.EntityState); // EntityState.Unchanged; 21 22 23/**//**//**////STAGE 3: Changed 24/**//// By modifying a property the entity will automatically 25/**//// change state to an EntityState.Changed state. 26 customer.Region ="Under The Sea"; 27 Response.Write(customer.EntityState); // EntityState.Changed; 28 DataRepository.CustomersProvider.Save(customer); 29 30 31/**//**//**////STAGE 4: Deleted 32/**//// Two ways exist being in an EntityState.Deleted state for an Entity. 33/**//// MarkToDelete() method, or directly calling Delete in the repository. 34/**//// MarkToDelete() is mainly used when using the Save() method, 35/**//// wanting to delete an entity which aggregated 36/**//// and part of a Collection, a TList<Entity>. 37/**//// If you are working with a single entity as depicted, you would 38/**//// just pass the entire entity into the DataRepository for Deletion. 39 40/**////Using Delete Method Directly on the Entity 41 DataRepository.CustomersProvider.Delete(customer); 42 43/**//**//**////Using Save Method in DataRepository with MarkToDelete() 44 customer.MarkToDelete(); 45 Response.Write(customer.EntityState); // EntityState.Deleted; 46 DataRepository.CustomersProvider.Save(customer); 47 48/**//**//**////EntityState.Unchanged 49/**////Say I want to delete all customers that have a city = Atlantis 50/**//// Whenever you get any entity items from the Database, once created 51/**//// the state is immediately changed to EntityState.Unchanged 52 TList<Customers> myList = DataRepository.CustomersProvider.GetByCity("Atlantis"); 53 54for (int i =0; i < myList.Count; i++) 55 ......{ 56 Response.Write(myList[i].EntityState); // EntityState.Unchanged; 57 myList.RemoveEntity(myList[i]); 58 59 Response.Write(myList[i].EntityState); // EntityState.Deleted; 60 } 61 62/**//**//**//// Now you've actually removed the entities from the list 63 Response.Write(myList.Count); // Prints 0 64 65/**//**//**//// They are however moved to a DeletedItems collection 66 Response.Write(myList.DeletedItems.Count); //Prints 1 67 68/**//**//**////Will delete the items from the Database 69 DataRepository.CustomersProvider.Save(myList); 70 71/**//**//**////Or you can Iterate the list calling MarkToDelete(); 72 myList.ForEach( 73delegate(Customers c) 74 ......{ 75 c.MarkToDelete(); 76 } 77 ); 78 79 80 81/**//**//**////Will persist all of the Deleted entities. 82 DataRepository.CustomersProvider.Save(myList); Edit Base State Behavior You can override the default behavior if you wanted and managed how EntityState was used. Perhaps if you wanted to use a StateMachine instead to manage state. Overall, it's a flexible approach that should let you customize however you need to.. There are also some entity state descriptor properties such as IsDeleted, IsDirty, IsNew. One other thing to note, is that you can remove the flag after using MarkToDelete by calling RemoveDeleteMark(). Excerpt from EntityBase.generated.cs 1/**//**//**////<summary> 2/**//// True if object has been <see cref="MarkToDelete"/>. ReadOnly. 3/**////</summary> 4 [BrowsableAttribute(false), XmlIgnoreAttribute()] 5publicbool IsDeleted 6 ......{ 7get ......{ returnthis.currentEntityState == EntityState.Deleted; } 8 } 9 10 11/**//**//**////<summary> 12/**//// Indicates if the object has been modified from its original state. 13/**////</summary> 14/**////<remarks>True if object has been modified; otherwise False;</remarks> 15 [BrowsableAttribute(false), XmlIgnoreAttribute()] 16publicbool IsDirty 17 ......{ 18get 19 ......{ 20returnthis.currentEntityState != EntityState.Unchanged 21&&this.currentEntityState != EntityState.Added; 22 } 23 } 24 25/**//**//**////<summary> 26/**//// Indicates if the object is new. 27/**////</summary> 28/**////<remarks>True if objectis new; otherwise False;</remarks> 29 [BrowsableAttribute(false), XmlIgnoreAttribute()] 30publicbool IsNew 31 ......{ 32get ......{ returnthis.currentEntityState == EntityState.Added; } 33set ......{ this.currentEntityState = EntityState.Added; } 34 } 35 36 37/**//**//**////<summary> 38/**//// Indicates state of object 39/**////</summary> 40/**////<remarks>0=Unchanged, 1=Added, 2=Changed</remarks> 41 [BrowsableAttribute(false), XmlIgnoreAttribute()] 42publicvirtual EntityState EntityState 43 ......{ 44get ......{ returnthis.currentEntityState; } 45set ......{ this.currentEntityState = value; } 46 } 47 48 49/**//**//**////<summary> 50/**//// Accepts the changes made to this object. 51/**////</summary> 52/**////<remarks> 53/**//// After calling this method <see cref="IsDirty"/> and <see cref="IsNew"/> are false. 54/**////<see cref="IsDeleted"/> flag remain unchanged as it is handled by the parent List. 55/**////</remarks> 56publicvirtualvoid AcceptChanges() 57 ......{ 58this.bindingIsNew =false; 59this.currentEntityState = EntityState.Unchanged; 60 OnPropertyChanged(string.Empty); 61 } 62 63/**//**//**////<summary> 64/**//// Revert all changes and restore original values. 65/**//// Currently not supported. 66/**////</summary> 67/**////<exception cref="NotSupportedException">This method throws exception.</exception> 68publicabstractvoid CancelChanges(); 69 70/**//**//**////<summary> 71/**//// Marks entity to be deleted. 72/**////</summary> 73publicvirtualvoid MarkToDelete() 74 ......{ 75if (this.currentEntityState != EntityState.Added) 76this.currentEntityState = EntityState.Deleted; 77 } 78 79 80/**//**//**////<summary> 81/**//// Remove the "isDeleted" mark from the entity. 82/**////</summary> 83publicvirtualvoid RemoveDeleteMark() 84 ......{ 85if (this.currentEntityState != EntityState.Added) 86 ......{ 87this.currentEntityState = EntityState.Changed; 88 } 89 } Edit Interface Implementations The entities themselves implement several interfaces to provide the full featured needs of consuming layers. The first two layers are custom .netTiers interfaces, the rest are from the System.ComponentModel and System.Runtime.Serialization namespaces. Some of these interfaces are : IEntityId - Gives exposure to an encapuslated primary key for your entity. Supports containment of composite primary keys. IEntity- A .netTiers interface that provides all the functionality required for a .netTiers entity. IComparable - Implements the ability to compare two entities types. ICloneable - Implements the ability to clone an entity IEditableObject - Implements the ability to commit or rollback changes to an object that is used as a datasource. IComponent - Implements functionality required by all .Net System.ComponetModel Components. INotifyPropertyChanged - Notifies subscribed clients that a property value has changed. IDataErrorInfo - Provides the functionality to offer custom error information that a user interface can bind to. IDeserializationCallback - Indicates that a classis to be notified when deserialization of the entire object graph has been completed. Edit What about generated views? Are they entities? Generated views object types are not considered entities, although they share many similar attributes. View objects do not maintain state because they currently can not be persisted back into the database. Edit Entity Validation Rule Engine One of the most powerful features that .netTiers provides to manage the integrity of your data is the Entity Rule Engine. This implements IDataErrorInfo in the EntityBase.generated.cs class. It provides the framework for managing entity business rules and custom error information that a user interface can bind to. Controls such as the DataGridView automatically detect thisinterface and provide error icons along with descriptions about the error. There are several properties that assist you in managing your business rules. There are several built in validators ready to use out of the box. NotNull - Determines the if the database column accepts null values. StringMaxLength - Compares against the column width for the property. StringRequired - Determines if the column allows empty string entries. MaxWords - Determines whether the property has exceeted the maximum amount of words RegexIsMatch - Determines whether current property matches the regular expression LessThanOrEqualToValue - Less than or equal to current value of property LessThanValue -- Less than current value of property EqualsValue - equals current value of property GreaterThanValue - Greater than current value of property GreaterThanOrEqualToValue - Greater than or equal to current value of property CompareValues - Compares values of T using a comparer InRange - Ensures T is within a min and max of a Range using a Comparer. However, we certainly understand that while those are all very useful, they do not cover the spectrum of potentially business rules. There is most important aspect of the rule engine that all of the Validators are validated by a delegate which is called ValidationRuleHandler, through which you can set up any ValidationRule, so longas it returns a bool value. The target parameter is the object being validated, while e is a ValidationRuleArgs object that contians information about the rule (property to validate, error description). There are a couple of more properties that are of interest. There is now a property called IsValid that checks the rules to see if any have been broken. You can also get all of the broken rules through the BrokenRulesList property in your entity. Validation/ValidationRuleHandler.cs 1/**//**//**////<summary> 2/**//// Delegate providing method sig that will process validation rules. 3/**////</summary> 4/**////<remarks> 5/**////<para> 6/**//// The method handler should set the Description attribute of the 7/**////<see cref="ValidationRuleArgs"/> parameter so that a meaningful 8/**//// error is returned. 9/**////</para><para> 10/**//// If the data is valid, the method must return true. If invalid, 11/**//// the Description should be set the false should be returned. 12/**////</para> 13/**////</remarks> 14publicdelegatebool ValidationRuleHandler(object target, ValidationRuleArgs e); Edit Example of Auto-Generated Rules .netTiers will automatically detect the rules that apply for the database to maintain data integrity. However it's still extremely easy for you to add your own. Here's an example of automatically added rules for the Customer Entity we were working with. 1protectedoverridevoid AddValidationRules() 2......{ 3//Validation rules based on database schema. 4ValidationRules.AddRule(Validation.CommonRules.NotNull,"CustomerID"); 5 6ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 7new Validation.CommonRules.MaxLengthRuleArgs("CustomerID",5)); 8 9ValidationRules.AddRule(Validation.CommonRules.NotNull,"CompanyName"); 10 11ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 12new Validation.CommonRules.MaxLengthRuleArgs("CompanyName",40)); 13 14ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 15new Validation.CommonRules.MaxLengthRuleArgs("ContactName",30)); 16 17ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 18new Validation.CommonRules.MaxLengthRuleArgs("ContactTitle",30)); 19 20ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 21new Validation.CommonRules.MaxLengthRuleArgs("Address",60)); 22 23ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 24new Validation.CommonRules.MaxLengthRuleArgs("City",15)); 25 26ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 27new Validation.CommonRules.MaxLengthRuleArgs("Region",15)); 28 29ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 30new Validation.CommonRules.MaxLengthRuleArgs("PostalCode",10)); 31 32ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 33new Validation.CommonRules.MaxLengthRuleArgs("Country",15)); 34 35ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 36new Validation.CommonRules.MaxLengthRuleArgs("Phone",24)); 37 38ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 39new Validation.CommonRules.MaxLengthRuleArgs("Fax",24)); 40 41} Edit That's great, but, how do I add my own rules? Adding your own rules is easy. There are really several ways to do it since th properties are exposed. The easiest is perhaps to simply override the AddRules() method in your entities and add your own rules along with ones that were generated for you. Here's an example of the Orders entity from the Northwind generation. Orders.cs -> The User customizable file for your entity class. 1/**//**//**////<summary> 2/**//// Adds custom validation rules to this object. 3/**////</summary> 4protectedoverridevoid AddValidationRules() 5......{ 6base.AddValidationRules(); 7 8//Add custom validation rules 9 ValidationRules.AddRule(Validation.CommonRules.StringRequired, "CustomerID"); 10 11 ValidationRules.AddRule(Validation.CommonRules.GreaterThanOrEqualToValue<Decimal?>, new Validation.CommonRules.CompareValueRuleArgs<Decimal?> ("Freight", 0)); 12 13 ValidationRules.AddRule( 14 Validation.CommonRules.LessThanOrEqualToValue<Decimal?>, 15new Validation.CommonRules.CompareValueRuleArgs<Decimal?>( 16"Freight", 200)); 17 18 19 ValidationRules.AddRule(ValidateOrderDate, "OrderDate"); 20} 21 22 23/**//**//**////<summary> 24/**//// Validates the order date. 25/**////</summary> 26/**////<param name="target">The target.</param> 27/**////<param name="e">The e.</param> 28/**////<returns></returns> 29privatebool ValidateOrderDate(object target, Validation.ValidationRuleArgs e) 30......{ 31if ((this.OrderDate ?? DateTime.MinValue) > DateTime.Today) 32 ......{ 33 e.Description ="The Order Date must not be in the future."; 34returnfalse; 35 } 36 37returntrue; 38} Edit So, how do I validate and see the error message? The easiest way to validate is when using a single entity is just to call the IsValid property. It will automatically trigger the validation process. You can also force the validation process by calling Validate(); 1 Orders o =new Orders(); 2 o.OrderDate =new DateTime(2001, 8, 29); 3 o.ShipAddress ="302 West Main Street"; 4 o.ShipCity ="Atlantis"; 5 o.ShipCountry ="Anywhere"; 6 o.ShipName ="Frank Sanders"; 7 o.ShipPostalCode ="55512"; 8 o.ShipRegion ="Under the Sea"; 9 10 11 o.Validate(); 12/**//**//**////Error property is a newline delimeted list of your broken rules. 13if (!o.IsValid) 14 lblMessage.Text = o.Error; 15 16 17 18/**//**//**////you can actually access all of the rules that were broken on the entity. 19foreach(BrokenRule rule in o.BrokenRulesList) 20 ......{ 21 lblMessage.Text =string.Format("<li>{0} - {1}</li>", 22 rule.Property, rule.Description); 23 } 24 25/**//**//**//// Suppose we have a partner vendor that 26/**//// processes orders for us, and we need 27/**//// to validate all of today's orders. 28/**//// Get today's orders and validate them. 29 TList<Orders> ordersList = GetOrdersFromVender(); 30if (!ordersList.IsValid) 31 ......{ 32 StringBuilder sb =new StringBuilder(); 33 sb.Append("<li>"); 34foreach(Orders o in ordersList.InvalidItems) 35 ......{ 36 sb.Append(o.Error.Replace("", "<li>")); 37 } 38 lblMessage.Text = sb.ToString(); 39 40 } Overall, the important thing to remember is that since the Rules engine uses delegates, which means that your logic can live any place you would like it to. There will be more coverage with complex business processes and validation in the Component Layer chapter. Edit Using Collections in .netTiers, TList & VList: .netTiers has two generic lists that it exclusively uses for your entities. TList and VList. The TList is the most full featured and only works with Types that implement IEntity, which are entities that are generated from a table as formerly stated. VList is a list for limited View Entities that don't maintain EntityState. 1 Orders order =new Orders(); 2 order.OrderDate =new DateTime(2001, 8, 29); 3 order.ShipAddress ="302 West Main Street"; 4 order.ShipCity ="Atlantis"; 5 order.ShipCountry ="Anywhere"; 6 order.ShipName ="Frank Sanders"; 7 order.ShipPostalCode ="55512"; 8 order.ShipRegion ="Under the Sea"; 9 10/**//**//**////Index Of, Get's the location of the order in the list 11int index = ordersList.IndexOf(order); 12 13/**//**//**////FindIndex 14/**////Returns the integer value if 15/**////one of the criteria matches your predicate 16 ordersList.FindIndex( 17delegate(Orders orders) 18 ......{ 19return orders.RequiredDate < DateTime.Today.AddDays(2); 20 }); 21 22 23/**//**//**////Insert 24/**////Useful if you want to insert an order in a specific location 25if (index <0) 26 ordersList.Insert(0, order); 27 28/**//**//**////Add 29/**////Appends an order to the list 30 ordersList.Add(order); 31 32 33/**//**//**////AddNew 34/**////Appends a new order to the list 35 ordersList.AddNew(); 36 ordersList[ordersList.Count -1].OrderDate = DateTime.Today; 37 38 39/**//**//**////RemoveEntity 40/**////Removes the order from the list and places it in DeletedItems 41 ordersList.RemoveEntity(order); 42 43/**//**//**////RemoveAt 44/**////Removes the first entry of the list 45 ordersList.RemoveAt(0); 46 47/**//**//**////RemoveAt 48/**////Removes the entity where it exists 49 ordersList.Remove(order); 50 51/**//**//**////ListChanged 52/**////Fires an event when the list has changed 53 ordersList.ListChanged += 54new System.ComponentModel.ListChangedEventHandler(ordersList_ListChanged); 55 56 57/**//**//**////IsDeletedCount 58/**////Returns the count of the DeletedItems Collection 59int deletedCount = ordersList.IsDeletedCount; 60 Debug.Assert(deletedCount == ordersList.DeletedItems.Count); 61 62/**//**//**////IsDirtyCount 63/**////Returns the count of the items that have an 64/**////EntityState == EntityState.Changed 65int dirtyCount = ordersList.IsDirtyCount; 66 Response.Write(string.Format("You have modified {0} entities.",dirtyCount)); 67 68/**//**//**////IsNewCount 69/**////Returns the count of the items that have an 70/**////EntityState == EntityState.Added 71int newCount = ordersList.IsNewCount; 72 Response.Write(string.Format("You have added {0} entities.", newCount)); 73 74/**//**//**////FindAllBy 75/**////Returns a new List of Entities that 76/**//// match the FindAllByType 77/**////FindAllByType.Contains, FindAllBy.StartsWith, FindAllByType.EndsWith 78 TList<Orders> sList = ordersList.FindAllBy(TList<Orders>.FindAllByType.StartsWith, 79 OrdersColumn.ShipCity, "Atl"); 80 81 TList<Orders> cList = ordersList.FindAllBy(TList<Orders>.FindAllByType.Contains, 82 OrdersColumn.ShipCity, "ant"); 83 84 TList<Orders> eList =ordersList.FindAllBy(TList<Orders>.FindAllByType.EndsWith, 85 OrdersColumn.ShipCity, "tis"); 86 87/**//**//**////FindAll 88/**////Returns a new List of Entities that match using the Table Enum Columns 89 TList<Orders> eqList = 90 ordersList.FindAll(OrdersColumn.ShipCity, "Atlantis"); 91 92 93/**//**//**////FindAll 94/**////Returns a new List of Entities using a predicate 95 TList<Orders> eqList2 = ordersList.FindAll( 96delegate(Orders o2)......{ 97return 98 o2.OrderDetailsCollection.Count >0&& 99 o2.OrderDate == DateTime.Today; 100 }); 101 102/**//**//**////Exists 103/**////Returns a bool if one of the criteria matches your predicate 104if (ordersList.Exists( 105delegate(Orders o3) 106 ......{ 107return 108 o3.OrderDetailsCollection.Count >0&& 109 o3.OrderDate == DateTime.Today; 110 })) 111 ......{ 112 Response.Write("There are orders today"); 113 } 114 115/**//**//**////ToArray 116/**////Creates an orders array from a list 117 Orders[] orderArray = ordersList.ToArray(); 118 119/**//**//**////ToDataSet 120/**////Creates a DataSet with children relationships from your TList. 121 DataSet ds = ordersList.ToDataSet(true); 122 123/**//**//**//// Filter as a string 124/**//// Creates a view inside of your list using a case sensitive filter 125/**//// Great for cached items that you need to show 126/**//// different sets of entities based on criteria. 127 ordersList.Filter ="ShipCity = 'Atlantis'"; 128 ordersList.ApplyFilter(); 129 ordersList.ForEach( 130delegate(Orders filteredOrder) 131 ......{ 132 Debug.Assert(filteredOrder.ShipCity =="Atlantis"); 133 }); 134 135/**//**//**////To Remove the filter, you simply call ResetFilter; 136 ordersList.RemoveFilter(); 137 138/**//**//**//// Filter using a Predicate delegate 139/**//// Great for needing to filter on items that 140/**//// different sets of entities based on criteria. 141 ordersList.ApplyFilter(GetValidAtlantisOrders); 142 ordersList.ForEach( 143delegate(Orders filteredOrder) 144 ......{ 145 Debug.Assert(filteredOrder.IsValid 146&& filteredOrder.ShipCity =="Atlantis"); 147 }); 148 149}//End Page_Load 150 151 152/**//**//**////<summary> 153/**//// Gets the valid atlantis orders. 154/**////</summary> 155/**////<param name="o">The o.</param> 156/**////<returns></returns> 157publicbool GetValidAtlantisOrders(Orders o) 158 ......{ 159return (o.IsValid 160&& o.ShipCity =="Atlantis" 161&& o.OrderDetailsCollection.Count >0 162&& o.OrderDetailsCollection.IsValid); 163 } 164 165void ordersList_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e) 166 ......{ 167thrownew Exception("The method or operation is not implemented."); 168 } 169 170/**//**//**////<summary> 171/**//// Gets the orders from vendor. Stub method, does nothing. 172/**////</summary> 173/**////<returns></returns> 174public TList <Orders> GetOrdersFromVendor() 175 ......{ 176//Get Some orders from a vendor 177returnnew TList<Orders>(); 178 } 179} Edit Entity Management Framework: In any application there are often several aspects of your application that you commonly have to doin order to optimize your application. Edit EntityFactoryBase The EntityFactoryBase is a creational construct that exists to assist the creation of entities of an unknown type at runtime. Entities are/were normally created in the DataRepository in a given EntityProvider's Fill method. So if I had DataRepository.MyEntityProvider, there would be a method called Fill that took an IDataReader, an TList (EntityCollection) and a row params. This method is actually going to hydrate the entities when coming back from the DataRepository. This version of the templates allow you to create component business objects which inherit from the entity objects. Since these component objects live in the tier on top of the Data Access Layer and Entities. Since the DataRepository creates entities for usage, it's not possible to create those types because the DAL deosn't know about the smart component business objects, only the Entity DTO objects. The role the EntityFactory is used foris you have the ability to define which factory will be used to create your objects to be filled in the app/web.config. Example: 1entityFactoryType="Northwind.Entities.EntityFactory"; 2// OR 3entityFactoryType="Northwind.Entities.ComponentEntityFactory"; Each factory will use the namespace of the factory to create unkonwn types at runtime using an Activator. This type discovery is cached and so you only face a perf hit once. There are events that you can subscribe to during this process to inject some logic before the objectis created and just after it's created but before being hydrated. This is useful if you wanted to attach your own events to the entity. Edit EntityCache The EntityCache class manages the lifetime of entities that you would like to not have to be queried for all the time. In reality, thisclass simply wraps the Enterprise Library Cache. EntLib offers a full featured and configurable object cache. The entity cache can be used by any object, and does not have to be an entity. More info can be found here: You don't "Have" to configure the cache to work, .netTiers will generate a default cache configuration at runtime if one does not exist, but it's recommended that you do create a configuration for your caching block to optimize the cache settings for your application. The entity cache can easily be configured by pointing your Enterprise Library Configurator tool at your app/web.config. We've also recently started including a sample default settings entlib.config in the MyNamespace.UnitTest project. Edit IEntityCacheItem When this marker interfaceis applied to an entity, the entity will automatically be placed into cache. The interface provides lifetime and callback parameters used to manage the caching of your entities. This is an interface that you would have to apply yourself to the entity at the concrete class level. Edit EntityLocator The EntityLocator sits on top of the Locator class of the Microsoft Patterns and Practices Group's ObjectBuilder Framework. The locator is responsible for creating a WeakReference'd Object Store so that as your application is handling a high volume of entities, which many are of the same record, we will return to you the same objectfor all references until that entity is persisted to the DataRepository. Combining this feature with Optimistic Concurrency with a Timestamp on your Table, you'll end up saving quite a bit on memory consumption. And for those that might not know, a weak reference means that the objects will still be garbage collected as soon as there are no more actual references to that entity any longer. This feature has to be enabled in the app/web.config under enableEntityTracking="true/false" Edit EntityManager The EntityManager is the glue that holds it all together, and should be considered the entry point to most of these features, with the exception of the EntityCache. When an objectis about to be created, and DataRepository.Provider.EntityTracking is enabled, the EntityManager get's called. The EntityManager contains a single EntityLocator object and a collection of EntityCache objects, for all of your different entity cache providers. Most likely though, there will only be a single EntityCache object in there. The EntityManager contains a LocateOrCreate method that determine if an entity already exists and is currently being referenced, if so, then return that entity, otherwise, create a new one using the entity factory defined and begin tracking the entity. There are several yet to be implemented features which we have in mind for the EntityManager such as managing meta data amongst the entities and being able to determine relationship boundaries at runtime.
Table of Contents [Hide/Show]Entity Layer What is an Entity? A bit of history: The Entity Relationship Model Whats your definition of an entity? EntityBase What is Entity St