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
///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
1 /**//// <summary> 2 /// List of possible state for an entity. 3 /// </summary> 4 public enum 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 }
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 54 for (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( 73 delegate(Customers c) 74 ...{ 75 c.MarkToDelete(); 76 } 77 ); 78 79 80 81 /**////Will persist all of the Deleted entities. 82 DataRepository.CustomersProvider.Save(myList);
1 /**//// <summary> 2 /// True if object has been <see cref="MarkToDelete"/>. ReadOnly. 3 /// </summary> 4 [BrowsableAttribute(false), XmlIgnoreAttribute()] 5 public bool IsDeleted 6 ...{ 7 get ...{ return this.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()] 16 public bool IsDirty 17 ...{ 18 get 19 ...{ 20 return this.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()] 30 public bool IsNew 31 ...{ 32 get ...{ return this.currentEntityState == EntityState.Added; } 33 set ...{ 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()] 42 public virtual EntityState EntityState 43 ...{ 44 get ...{ return this.currentEntityState; } 45 set ...{ 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> 56 public virtual void AcceptChanges() 57 ...{ 58 this.bindingIsNew = false; 59 this.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> 68 public abstract void CancelChanges(); 69 70 /**////<summary> 71 /// Marks entity to be deleted. 72 ///</summary> 73 public virtual void MarkToDelete() 74 ...{ 75 if (this.currentEntityState != EntityState.Added) 76 this.currentEntityState = EntityState.Deleted; 77 } 78 79 80 /**////<summary> 81 /// Remove the "isDeleted" mark from the entity. 82 ///</summary> 83 public virtual void RemoveDeleteMark() 84 ...{ 85 if (this.currentEntityState != EntityState.Added) 86 ...{ 87 this.currentEntityState = EntityState.Changed; 88 } 89 }
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> 14 public delegate bool ValidationRuleHandler(object target, ValidationRuleArgs e);
1protected override void AddValidationRules() 2...{ 3//Validation rules based on database schema. 4ValidationRules.AddRule(Validation.CommonRules.NotNull,"CustomerID"); 5 6ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 7 new Validation.CommonRules.MaxLengthRuleArgs("CustomerID",5)); 8 9ValidationRules.AddRule(Validation.CommonRules.NotNull,"CompanyName"); 10 11ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 12 new Validation.CommonRules.MaxLengthRuleArgs("CompanyName",40)); 13 14ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 15 new Validation.CommonRules.MaxLengthRuleArgs("ContactName",30)); 16 17ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 18 new Validation.CommonRules.MaxLengthRuleArgs("ContactTitle",30)); 19 20ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 21 new Validation.CommonRules.MaxLengthRuleArgs("Address",60)); 22 23ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 24 new Validation.CommonRules.MaxLengthRuleArgs("City",15)); 25 26ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 27 new Validation.CommonRules.MaxLengthRuleArgs("Region",15)); 28 29ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 30 new Validation.CommonRules.MaxLengthRuleArgs("PostalCode",10)); 31 32ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 33 new Validation.CommonRules.MaxLengthRuleArgs("Country",15)); 34 35ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 36 new Validation.CommonRules.MaxLengthRuleArgs("Phone",24)); 37 38ValidationRules.AddRule(Validation.CommonRules.StringMaxLength, 39 new Validation.CommonRules.MaxLengthRuleArgs("Fax",24)); 40 41}
1/**//// <summary> 2/// Adds custom validation rules to this object. 3/// </summary> 4protected override void AddValidationRules() 5...{ 6 base.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?>, 15 new 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> 29private bool ValidateOrderDate(object target, Validation.ValidationRuleArgs e) 30...{ 31 if ((this.OrderDate ?? DateTime.MinValue) > DateTime.Today) 32 ...{ 33 e.Description = "The Order Date must not be in the future."; 34 return false; 35 } 36 37 return true; 38}
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. 13 if (!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. 19 foreach(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(); 30 if (!ordersList.IsValid) 31 ...{ 32 StringBuilder sb = new StringBuilder(); 33 sb.Append("<li>"); 34 foreach(Orders o in ordersList.InvalidItems) 35 ...{ 36 sb.Append(o.Error.Replace("\n", "<li>")); 37 } 38 lblMessage.Text = sb.ToString(); 39 40 }
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 11 int index = ordersList.IndexOf(order); 12 13 /**////FindIndex 14 ///Returns the integer value if 15 ///one of the criteria matches your predicate 16 ordersList.FindIndex( 17 delegate(Orders orders) 18 ...{ 19 return orders.RequiredDate < DateTime.Today.AddDays(2); 20 }); 21 22 23 /**////Insert 24 ///Useful if you want to insert an order in a specific location 25 if (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 += 54 new System.ComponentModel.ListChangedEventHandler(ordersList_ListChanged); 55 56 57 /**////IsDeletedCount 58 ///Returns the count of the DeletedItems Collection 59 int 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 65 int 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 71 int 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( 96 delegate(Orders o2)...{ 97 return 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 104 if (ordersList.Exists( 105 delegate(Orders o3) 106 ...{ 107 return 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( 130 delegate(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( 143 delegate(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> 157 public bool GetValidAtlantisOrders(Orders o) 158 ...{ 159 return (o.IsValid 160 && o.ShipCity == "Atlantis" 161 && o.OrderDetailsCollection.Count > 0 162 && o.OrderDetailsCollection.IsValid); 163 } 164 165 void ordersList_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e) 166 ...{ 167 throw new 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> 174 public TList <Orders> GetOrdersFromVendor() 175 ...{ 176 //Get Some orders from a vendor 177 return new TList<Orders>(); 178 } 179}
1entityFactoryType="Northwind.Entities.EntityFactory"; 2// OR 3entityFactoryType="Northwind.Entities.ComponentEntityFactory";