Work in progress for the Ordering microservice Domain Model
This commit is contained in:
		
							parent
							
								
									b6befd623a
								
							
						
					
					
						commit
						9aed8221f2
					
				
							
								
								
									
										11
									
								
								src/Services/Ordering/Ordering.API/DTO/OrderDTO.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/Services/Ordering/Ordering.API/DTO/OrderDTO.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  | 
 | ||||||
|  | namespace Microsoft.eShopOnContainers.Services.Ordering.API.DTO | ||||||
|  | { | ||||||
|  |     public class OrderDTO | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								src/Services/Ordering/Ordering.API/DTO/OrderItemDTO.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/Services/Ordering/Ordering.API/DTO/OrderItemDTO.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | |||||||
|  | using System; | ||||||
|  | using System.Runtime.Serialization; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.Order | ||||||
|  | { | ||||||
|  |     [DataContract] | ||||||
|  |     public sealed class OrderItemDTO | ||||||
|  |     { | ||||||
|  |         public OrderItemDTO() { } | ||||||
|  | 
 | ||||||
|  |         [DataMember] | ||||||
|  |         public Guid Id { get; set; } | ||||||
|  | 
 | ||||||
|  |         [DataMember] | ||||||
|  |         public int Quantity { get; set; } | ||||||
|  | 
 | ||||||
|  |         [DataMember] | ||||||
|  |         public int FulfillmentRemaining { get; set; } | ||||||
|  | 
 | ||||||
|  |         public override string ToString() | ||||||
|  |         { | ||||||
|  |             return String.Format("ID: {0}, Quantity: {1}, Fulfillment Remaing: {2}", this.ItemId, this.Quantity, this.FulfillmentRemaining); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,56 @@ | |||||||
|  | using System; | ||||||
|  | using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; | ||||||
|  | 
 | ||||||
|  | namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel | ||||||
|  | { | ||||||
|  |         public class Buyer : AggregateRoot | ||||||
|  |         { | ||||||
|  |             public Buyer(Guid buyerId, string name, string lastName, string email, Address address, string phoneNumber) | ||||||
|  |             { | ||||||
|  |                 this.BuyerId = buyerId; | ||||||
|  |                 this.Name = name; | ||||||
|  |                 this.LastName = lastName; | ||||||
|  |                 this.Email = email; | ||||||
|  |                 this.Address = address; | ||||||
|  |                 this.PhoneNumber = phoneNumber; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             protected Buyer() { } // infrastructure | ||||||
|  | 
 | ||||||
|  |             public virtual Guid BuyerId | ||||||
|  |             { | ||||||
|  |                 get; | ||||||
|  |                 private set; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             public virtual string Name | ||||||
|  |             { | ||||||
|  |                 get; | ||||||
|  |                 private set; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             public virtual string LastName | ||||||
|  |             { | ||||||
|  |                 get; | ||||||
|  |                 private set; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             public virtual string Email | ||||||
|  |             { | ||||||
|  |                 get; | ||||||
|  |                 private set; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             public virtual Address Address | ||||||
|  |             { | ||||||
|  |                 get; | ||||||
|  |                 private set; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             public virtual string PhoneNumber | ||||||
|  |             { | ||||||
|  |                 get; | ||||||
|  |                 private set; | ||||||
|  |             } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,64 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | 
 | ||||||
|  | using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; | ||||||
|  | 
 | ||||||
|  | namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel | ||||||
|  | { | ||||||
|  |     public class Address : ValueObject<Address> //A VO doesn't have IDENTITY, like in this case, the Address | ||||||
|  |     { | ||||||
|  |         public virtual String Street | ||||||
|  |         { | ||||||
|  |             get; | ||||||
|  |             private set; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public virtual String City | ||||||
|  |         { | ||||||
|  |             get; | ||||||
|  |             private set; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public virtual String State | ||||||
|  |         { | ||||||
|  |             get; | ||||||
|  |             private set; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public virtual String StateCode | ||||||
|  |         { | ||||||
|  |             get; | ||||||
|  |             private set; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public virtual String Country | ||||||
|  |         { | ||||||
|  |             get; | ||||||
|  |             private set; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public virtual String CountryCode | ||||||
|  |         { | ||||||
|  |             get; | ||||||
|  |             private set; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public virtual String ZipCode | ||||||
|  |         { | ||||||
|  |             get; | ||||||
|  |             private set; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public virtual double Latitude | ||||||
|  |         { | ||||||
|  |             get; | ||||||
|  |             private set; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public virtual double Longitude | ||||||
|  |         { | ||||||
|  |             get; | ||||||
|  |             private set; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,77 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  | 
 | ||||||
|  | using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; | ||||||
|  | 
 | ||||||
|  | namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel | ||||||
|  | { | ||||||
|  |     public class Order : AggregateRoot | ||||||
|  |     { | ||||||
|  |         public Order(Guid buyerId, Address shippingAddress, Address billingAddress) | ||||||
|  |               : this(buyerId, shippingAddress, billingAddress, DateTime.UtcNow) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public Order(Guid buyerId, Address shippingAddress, Address billingAddress, DateTime orderDate) | ||||||
|  |         { | ||||||
|  |             this.BuyerId = buyerId; | ||||||
|  |             this.ShippingAddress = shippingAddress; | ||||||
|  |             this.BillingAddress = billingAddress; | ||||||
|  |             this.OrderDate = orderDate; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         protected Order() { } // Infrastructure. EF might need a plain constructor. Do not use. | ||||||
|  | 
 | ||||||
|  |         //Order ID comes derived from the Entity base class | ||||||
|  | 
 | ||||||
|  |         List<OrderItem> _orderItems; | ||||||
|  |         public virtual List<OrderItem> orderItems | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 if (_orderItems == null) | ||||||
|  |                     _orderItems = new List<OrderItem>(); | ||||||
|  | 
 | ||||||
|  |                 return _orderItems; | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             private set | ||||||
|  |             { | ||||||
|  |                 _orderItems = value; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public virtual Guid BuyerId | ||||||
|  |         { | ||||||
|  |             get; | ||||||
|  |             private set; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public virtual Address ShippingAddress | ||||||
|  |         { | ||||||
|  |             get; | ||||||
|  |             private set; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public virtual Address BillingAddress | ||||||
|  |         { | ||||||
|  |             get; | ||||||
|  |             private set; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public virtual DateTime OrderDate | ||||||
|  |         { | ||||||
|  |             get; | ||||||
|  |             private set; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public virtual OrderStatus Status | ||||||
|  |         { | ||||||
|  |             get; | ||||||
|  |             set; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,35 @@ | |||||||
|  | using System; | ||||||
|  | using System.Runtime.Serialization; | ||||||
|  | 
 | ||||||
|  | using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; | ||||||
|  | 
 | ||||||
|  | namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel | ||||||
|  | { | ||||||
|  |     public class OrderItem : Entity | ||||||
|  |     { | ||||||
|  |         //(CDLTLL) Might remove this constructor so | ||||||
|  |         // just with a method in the Order-AggregateRoot you can add an OrderItem.. | ||||||
|  |         //public OrderItem(Guid itemId, decimal itemPrice, int quantity) | ||||||
|  |         //{ | ||||||
|  |         //    this.Id = itemId; | ||||||
|  |         //    this.ItemPrice = itemPrice; | ||||||
|  |         //    this.Quantity = quantity; | ||||||
|  |         //    this.FulfillmentRemaining = quantity;  <---- Put this logic into the AggregateRoot method AddOrderItem() | ||||||
|  |         //} | ||||||
|  | 
 | ||||||
|  |         protected OrderItem() { } // Infrastructure. EF might need a plain constructor. Do not use. | ||||||
|  | 
 | ||||||
|  |         public Guid ItemId { get; set; } | ||||||
|  | 
 | ||||||
|  |         public decimal ItemPrice { get; set; } | ||||||
|  | 
 | ||||||
|  |         public int Quantity { get; set; } | ||||||
|  | 
 | ||||||
|  |         public int FulfillmentRemaining { get; set; } | ||||||
|  | 
 | ||||||
|  |         public override string ToString() | ||||||
|  |         { | ||||||
|  |             return String.Format("ID: {0}, Quantity: {1}, Fulfillment Remaing: {2}", this.ItemId, this.Quantity, this.FulfillmentRemaining); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,18 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  | 
 | ||||||
|  | namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel | ||||||
|  | { | ||||||
|  |     public enum OrderStatus | ||||||
|  |     { | ||||||
|  |         Unknown, | ||||||
|  |         New, | ||||||
|  |         Submitted, | ||||||
|  |         InProcess, | ||||||
|  |         Backordered, | ||||||
|  |         Shipped, | ||||||
|  |         Canceled, | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,11 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  | 
 | ||||||
|  | namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.RepositoryContracts | ||||||
|  | { | ||||||
|  |     interface IBuyerRepository | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,17 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  | 
 | ||||||
|  | using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel; | ||||||
|  | using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; | ||||||
|  | 
 | ||||||
|  | namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.RepositoryContracts | ||||||
|  | { | ||||||
|  |     public interface IOrderRepository : IRepository<Order> | ||||||
|  |     { | ||||||
|  |         Order Get(int associatedConferenceId); | ||||||
|  | 
 | ||||||
|  |         void ModifyOrder(Order seatOrder); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -5,7 +5,7 @@ using System.Threading.Tasks; | |||||||
| 
 | 
 | ||||||
| namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork | namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork | ||||||
| { | { | ||||||
|     public class AggregateRoot |     public class AggregateRoot : Entity | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,11 +1,130 @@ | |||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; |  | ||||||
| using System.Linq; |  | ||||||
| using System.Threading.Tasks; |  | ||||||
| 
 | 
 | ||||||
| namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork | namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork | ||||||
| { | { | ||||||
|     public class Entity |     /// <summary> | ||||||
|  |     /// Base class for entities | ||||||
|  |     /// </summary> | ||||||
|  |     public abstract class Entity | ||||||
|     { |     { | ||||||
|  |         //Members | ||||||
|  | 
 | ||||||
|  |         int? _requestedHashCode; | ||||||
|  |         Guid _Id; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         //Properties | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Get the persisten object identifier | ||||||
|  |         /// </summary> | ||||||
|  |         public virtual  Guid Id  | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 return _Id; | ||||||
|  |             } | ||||||
|  |             protected set | ||||||
|  |             { | ||||||
|  |                 _Id = value; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         //Public Methods | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Check if this entity is transient, ie, without identity at this moment | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns>True if entity is transient, else false</returns> | ||||||
|  |         public bool IsTransient() | ||||||
|  |         { | ||||||
|  |             return this.Id == Guid.Empty; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Generate identity for this entity | ||||||
|  |         /// </summary> | ||||||
|  |         public void GenerateNewIdentity() | ||||||
|  |         { | ||||||
|  |             if ( IsTransient()) | ||||||
|  |                 this.Id = IdentityGenerator.NewSequentialGuid(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Change current identity for a new non transient identity | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="identity">the new identity</param> | ||||||
|  |         public void ChangeCurrentIdentity(Guid identity) | ||||||
|  |         { | ||||||
|  |             if ( identity != Guid.Empty) | ||||||
|  |                 this.Id = identity; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         //Overrides Methods | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// <see cref="M:System.Object.Equals"/> | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="obj"><see cref="M:System.Object.Equals"/></param> | ||||||
|  |         /// <returns><see cref="M:System.Object.Equals"/></returns> | ||||||
|  |         public override bool Equals(object obj) | ||||||
|  |         { | ||||||
|  |             if (obj == null || !(obj is Entity)) | ||||||
|  |                 return false; | ||||||
|  | 
 | ||||||
|  |             if (Object.ReferenceEquals(this, obj)) | ||||||
|  |                 return true; | ||||||
|  | 
 | ||||||
|  |             Entity item = (Entity)obj; | ||||||
|  | 
 | ||||||
|  |             if (item.IsTransient() || this.IsTransient()) | ||||||
|  |                 return false; | ||||||
|  |             else | ||||||
|  |                 return item.Id == this.Id; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// <see cref="M:System.Object.GetHashCode"/> | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns><see cref="M:System.Object.GetHashCode"/></returns> | ||||||
|  |         public override int GetHashCode() | ||||||
|  |         { | ||||||
|  |             if (!IsTransient()) | ||||||
|  |             { | ||||||
|  |                 if (!_requestedHashCode.HasValue) | ||||||
|  |                     _requestedHashCode = this.Id.GetHashCode() ^ 31; // XOR for random distribution (http://blogs.msdn.com/b/ericlippert/archive/2011/02/28/guidelines-and-rules-for-gethashcode.aspx) | ||||||
|  | 
 | ||||||
|  |                 return _requestedHashCode.Value; | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |                 return base.GetHashCode(); | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  |         /// <summary> | ||||||
|  |         /// equals operator | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="left">left parameter</param> | ||||||
|  |         /// <param name="right">right parameter</param> | ||||||
|  |         /// <returns>true if equals</returns> | ||||||
|  |         public static bool operator ==(Entity left, Entity right) | ||||||
|  |         { | ||||||
|  |             if (Object.Equals(left, null)) | ||||||
|  |                 return (Object.Equals(right, null)) ? true : false; | ||||||
|  |             else | ||||||
|  |                 return left.Equals(right); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Distinct operator | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="left">left parameter</param> | ||||||
|  |         /// <param name="right">right parameter</param> | ||||||
|  |         /// <returns>True if different</returns> | ||||||
|  |         public static bool operator !=(Entity left, Entity right) | ||||||
|  |         { | ||||||
|  |             return !(left == right); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,93 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Linq.Expressions; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  | 
 | ||||||
|  | namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  |     /// <summary> | ||||||
|  |     /// Base interface for implement a "Repository Pattern", for | ||||||
|  |     /// more information about this pattern see http://martinfowler.com/eaaCatalog/repository.html | ||||||
|  |     /// or http://blogs.msdn.com/adonet/archive/2009/06/16/using-repository-and-unit-of-work-patterns-with-entity-framework-4-0.aspx | ||||||
|  |     /// </summary> | ||||||
|  |     /// <remarks> | ||||||
|  |     /// Indeed, DbSet is already a generic repository and therefore you would not need a Repo.  | ||||||
|  |     /// But using this Repo interface allows us to ensure PI (Persistence Ignorant) principle | ||||||
|  |     /// within our domain model | ||||||
|  |     /// </remarks> | ||||||
|  |     /// <typeparam name="TEntity">Type of entity for this repository </typeparam> | ||||||
|  |     public interface IRepository<TEntity> : IDisposable | ||||||
|  |         where TEntity : Entity | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// Get the unit of work in this repository | ||||||
|  |         /// </summary> | ||||||
|  |         IUnitOfWork UnitOfWork { get; } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Add item into repository | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="item">Item to add to repository</param> | ||||||
|  |         void Add(TEntity item); | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Delete item  | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="item">Item to delete</param> | ||||||
|  |         void Remove(TEntity item); | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Set item as modified | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="item">Item to modify</param> | ||||||
|  |         void Modify(TEntity item); | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         ///Track entity into this repository, really in UnitOfWork.  | ||||||
|  |         ///In EF this can be done with Attach and with Update in NH | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="item">Item to attach</param> | ||||||
|  |         void TrackItem(TEntity item); | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Sets modified entity into the repository.  | ||||||
|  |         /// When calling Commit() method in UnitOfWork  | ||||||
|  |         /// these changes will be saved into the storage | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="persisted">The persisted item</param> | ||||||
|  |         /// <param name="current">The current item</param> | ||||||
|  |         void Merge(TEntity persisted, TEntity current); | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Get element by entity key | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="id">Entity key value</param> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         TEntity Get(Guid id); | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Get all elements of type TEntity in repository | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns>List of selected elements</returns> | ||||||
|  |         IEnumerable<TEntity> GetAll(); | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Get all elements of type TEntity in repository | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="pageIndex">Page index</param> | ||||||
|  |         /// <param name="pageCount">Number of elements in each page</param> | ||||||
|  |         /// <param name="orderByExpression">Order by expression for this query</param> | ||||||
|  |         /// <param name="ascending">Specify if order is ascending</param> | ||||||
|  |         /// <returns>List of selected elements</returns> | ||||||
|  |         IEnumerable<TEntity> GetPaged<KProperty>(int pageIndex, int pageCount, Expression<Func<TEntity, KProperty>> orderByExpression, bool ascending); | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Get  elements of type TEntity in repository | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="filter">Filter that each element do match</param> | ||||||
|  |         /// <returns>List of selected elements</returns> | ||||||
|  |         IEnumerable<TEntity> GetFiltered(Expression<Func<TEntity, bool>> filter); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,46 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  | 
 | ||||||
|  | namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// Contract for ‘UnitOfWork pattern’. For more | ||||||
|  |     /// related info see http://martinfowler.com/eaaCatalog/unitOfWork.html or | ||||||
|  |     /// http://msdn.microsoft.com/en-us/magazine/dd882510.aspx | ||||||
|  |     /// In this Microservice, the Unit Of Work is implemented using the out-of-box  | ||||||
|  |     /// Entity Framework Context (EF Core DbContext) persistence engine. But in order to | ||||||
|  |     /// comply the PI (Persistence Ignorant) principle in our Domain, we implement this interface/contract.  | ||||||
|  |     /// This interface/contract should be complied by any UoW implementation to be used with this Domain. | ||||||
|  |     /// </summary> | ||||||
|  |     public interface IUnitOfWork | ||||||
|  |         : IDisposable | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// Commit all changes made in a container. | ||||||
|  |         /// </summary> | ||||||
|  |         ///<remarks> | ||||||
|  |         /// If the entity have fixed properties and any optimistic concurrency problem exists,   | ||||||
|  |         /// then an exception is thrown | ||||||
|  |         ///</remarks> | ||||||
|  |         void Commit(); | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Commit all changes made in  a container. | ||||||
|  |         /// </summary> | ||||||
|  |         ///<remarks> | ||||||
|  |         /// If the entity have fixed properties and any optimistic concurrency problem exists, | ||||||
|  |         /// then 'client changes' are refreshed - Client wins | ||||||
|  |         ///</remarks> | ||||||
|  |         void CommitAndRefreshChanges(); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Rollback tracked changes. See references of UnitOfWork pattern | ||||||
|  |         /// </summary> | ||||||
|  |         void RollbackChanges(); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| @ -0,0 +1,47 @@ | |||||||
|  | using System; | ||||||
|  | 
 | ||||||
|  | namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork | ||||||
|  | { | ||||||
|  |     internal static class IdentityGenerator | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// This algorithm generates secuential GUIDs across system boundaries, ideal for databases  | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         public static Guid NewSequentialGuid() | ||||||
|  |         { | ||||||
|  |             byte[] uid = Guid.NewGuid().ToByteArray(); | ||||||
|  |             byte[] binDate = BitConverter.GetBytes(DateTime.UtcNow.Ticks); | ||||||
|  | 
 | ||||||
|  |             byte[] secuentialGuid = new byte[uid.Length]; | ||||||
|  |               | ||||||
|  |             secuentialGuid[0] = uid[0]; | ||||||
|  |             secuentialGuid[1] = uid[1]; | ||||||
|  |             secuentialGuid[2] = uid[2]; | ||||||
|  |             secuentialGuid[3] = uid[3]; | ||||||
|  |             secuentialGuid[4] = uid[4]; | ||||||
|  |             secuentialGuid[5] = uid[5]; | ||||||
|  |             secuentialGuid[6] = uid[6]; | ||||||
|  |             // set the first part of the 8th byte to '1100' so      | ||||||
|  |             // later we'll be able to validate it was generated by us    | ||||||
|  | 
 | ||||||
|  |             secuentialGuid[7] = (byte)(0xc0 | (0xf & uid[7])); | ||||||
|  | 
 | ||||||
|  |             // the last 8 bytes are sequential,     | ||||||
|  |             // it minimizes index fragmentation    | ||||||
|  |             // to a degree as long as there are not a large     | ||||||
|  |             // number of Secuential-Guids generated per millisecond   | ||||||
|  | 
 | ||||||
|  |             secuentialGuid[9] = binDate[0]; | ||||||
|  |             secuentialGuid[8] = binDate[1]; | ||||||
|  |             secuentialGuid[15] = binDate[2]; | ||||||
|  |             secuentialGuid[14] = binDate[3]; | ||||||
|  |             secuentialGuid[13] = binDate[4]; | ||||||
|  |             secuentialGuid[12] = binDate[5]; | ||||||
|  |             secuentialGuid[11] = binDate[6]; | ||||||
|  |             secuentialGuid[10] = binDate[7]; | ||||||
|  | 
 | ||||||
|  |             return new Guid(secuentialGuid); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										145
									
								
								src/Services/Ordering/Ordering.Domain/SeedWork/ValueObject.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								src/Services/Ordering/Ordering.Domain/SeedWork/ValueObject.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,145 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  | using System.Reflection; | ||||||
|  | 
 | ||||||
|  | namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// Base class for value objects in domain. | ||||||
|  |     /// Value | ||||||
|  |     /// </summary> | ||||||
|  |     /// <typeparam name="TValueObject">The type of this value object</typeparam> | ||||||
|  |     public class ValueObject<TValueObject> : IEquatable<TValueObject> | ||||||
|  |         where TValueObject : ValueObject<TValueObject> | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         //IEquatable and Override Equals operators | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// <see cref="M:System.Object.IEquatable{TValueObject}"/> | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="other"><see cref="M:System.Object.IEquatable{TValueObject}"/></param> | ||||||
|  |         /// <returns><see cref="M:System.Object.IEquatable{TValueObject}"/></returns> | ||||||
|  |         public bool Equals(TValueObject other) | ||||||
|  |         { | ||||||
|  |             if ((object)other == null) | ||||||
|  |                 return false; | ||||||
|  | 
 | ||||||
|  |             if (Object.ReferenceEquals(this, other)) | ||||||
|  |                 return true; | ||||||
|  | 
 | ||||||
|  |             //compare all public properties | ||||||
|  |             PropertyInfo[] publicProperties = this.GetType().GetProperties(); | ||||||
|  | 
 | ||||||
|  |             if ((object)publicProperties != null | ||||||
|  |                 && | ||||||
|  |                 publicProperties.Any()) | ||||||
|  |             { | ||||||
|  |                 return publicProperties.All(p => | ||||||
|  |                 { | ||||||
|  |                     var left = p.GetValue(this, null); | ||||||
|  |                     var right = p.GetValue(other, null); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |                     if (typeof(TValueObject).IsAssignableFrom(left.GetType())) | ||||||
|  |                     { | ||||||
|  |                         //check not self-references... | ||||||
|  |                         return Object.ReferenceEquals(left, right); | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                         return left.Equals(right); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |                 }); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |                 return true; | ||||||
|  |         } | ||||||
|  |         /// <summary> | ||||||
|  |         /// <see cref="M:System.Object.Equals"/> | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="obj"><see cref="M:System.Object.Equals"/></param> | ||||||
|  |         /// <returns><see cref="M:System.Object.Equals"/></returns> | ||||||
|  |         public override bool Equals(object obj) | ||||||
|  |         { | ||||||
|  |             if ((object)obj == null) | ||||||
|  |                 return false; | ||||||
|  | 
 | ||||||
|  |             if (Object.ReferenceEquals(this, obj)) | ||||||
|  |                 return true; | ||||||
|  | 
 | ||||||
|  |             ValueObject<TValueObject> item = obj as ValueObject<TValueObject>; | ||||||
|  | 
 | ||||||
|  |             if ((object)item != null) | ||||||
|  |                 return Equals((TValueObject)item); | ||||||
|  |             else | ||||||
|  |                 return false; | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  |         /// <summary> | ||||||
|  |         /// <see cref="M:System.Object.GetHashCode"/> | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns><see cref="M:System.Object.GetHashCode"/></returns> | ||||||
|  |         public override int GetHashCode() | ||||||
|  |         { | ||||||
|  |             int hashCode = 31; | ||||||
|  |             bool changeMultiplier = false; | ||||||
|  |             int index = 1; | ||||||
|  | 
 | ||||||
|  |             //compare all public properties | ||||||
|  |             PropertyInfo[] publicProperties = this.GetType().GetProperties(); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |             if ((object)publicProperties != null | ||||||
|  |                 && | ||||||
|  |                 publicProperties.Any()) | ||||||
|  |             { | ||||||
|  |                 foreach (var item in publicProperties) | ||||||
|  |                 { | ||||||
|  |                     object value = item.GetValue(this, null); | ||||||
|  | 
 | ||||||
|  |                     if ((object)value != null) | ||||||
|  |                     { | ||||||
|  | 
 | ||||||
|  |                         hashCode = hashCode * ((changeMultiplier) ? 59 : 114) + value.GetHashCode(); | ||||||
|  | 
 | ||||||
|  |                         changeMultiplier = !changeMultiplier; | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                         hashCode = hashCode ^ (index * 13);//only for support {"a",null,null,"a"} <> {null,"a","a",null} | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return hashCode; | ||||||
|  |         } | ||||||
|  |         /// <summary> | ||||||
|  |         ///  | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="left"></param> | ||||||
|  |         /// <param name="right"></param> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         public static bool operator ==(ValueObject<TValueObject> left, ValueObject<TValueObject> right) | ||||||
|  |         { | ||||||
|  |             if (Object.Equals(left, null)) | ||||||
|  |                 return (Object.Equals(right, null)) ? true : false; | ||||||
|  |             else | ||||||
|  |                 return left.Equals(right); | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  |         /// <summary> | ||||||
|  |         ///  | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="left"></param> | ||||||
|  |         /// <param name="right"></param> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         public static bool operator !=(ValueObject<TValueObject> left, ValueObject<TValueObject> right) | ||||||
|  |         { | ||||||
|  |             return !(left == right); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| @ -1,8 +1,10 @@ | |||||||
| { | { | ||||||
|   "version": "1.0.0-*", |   "version": "1.0.0-*", | ||||||
| 
 | 
 | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "NETStandard.Library": "1.6.0" |     "NETStandard.Library": "1.6.0", | ||||||
|  |     "System.Reflection.TypeExtensions": "4.1.0", | ||||||
|  |     "System.Runtime.Serialization.Primitives": "4.1.1" | ||||||
|   }, |   }, | ||||||
| 
 | 
 | ||||||
|   "frameworks": { |   "frameworks": { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user