Example #1
0
 /// <summary>
 /// This function will be called at the end of CreateSetupService and UpdateSetupService to setup any
 /// additional data in the dto used to display dropdownlists etc.
 /// It is also called at the end of the CreateService or UpdateService if there are errors, so that
 /// the data is available if the form needs to be reshown.
 /// This function should be overridden if the dto needs additional data setup
 /// </summary>
 /// <returns></returns>
 internal protected virtual async Task SetupSecondaryDataAsync(IGenericServicesDbContext db, TDto dto)
 {
     if (!SupportedFunctions.HasFlag(CrudFunctions.DoesNotNeedSetup))
     {
         throw new InvalidOperationException("SupportedFunctions flags say that setup of secondary data is needed, but did not override the SetupSecondaryData method.");
     }
 }
        /// <summary>
        /// This is used in an update. It copies only the properties in TDto that do not have the [DoNotCopyBackToDatabase] on them.
        /// You can override this if you need a more complex copy
        /// </summary>
        /// <param name="context"></param>
        /// <param name="source"></param>
        /// <param name="destination"></param>
        /// <return>status. destination is only valid if status.IsValid</return>
        protected internal virtual ISuccessOrErrors UpdateDataFromDto(IGenericServicesDbContext context, TDto source, TEntity destination)
        {
            var mapper = GenericServicesConfig.AutoMapperConfigs[CreateDictionaryKey <TDto, TEntity>()].CreateMapper();

            mapper.Map(source, destination);
            return(SuccessOrErrors.Success("Successful copy of data"));
        }
        private ISuccessOrErrors DeleteBloggerWithPost(IGenericServicesDbContext db, SimplePostDto post)
        {
            var blogger = db.Set <Blog>().SingleOrDefault(x => x.Name == post.BloggerName);

            db.Set <Blog>().Remove(blogger);
            return(SuccessOrErrors.Success("It was fine."));
        }
        //------------------------------------------------------------------------------------------
        //now the setup parts for the dropdown boxes

        /// <summary>
        /// This is called before a create and an update. It is an update if the dto key property is non zero.
        /// </summary>
        /// <param name="db"></param>
        /// <param name="dto"></param>
        protected override void SetupSecondaryData(IGenericServicesDbContext db, CrudSalesOrderDto dto)
        {
            var getPossibleAddresses = db.Set <CustomerAddress>().Include(x => x.Address).Where(x => x.CustomerID == dto.CustomerID).ToList();

            dto.ShipToOptions.SetupDropDownListContent(
                getPossibleAddresses.Select(
                    y =>
                    new KeyValuePair <string, string>(ListCustomerAddressDto.FormCustomerAddressFormatted(y),
                                                      y.AddressID.ToString("D"))),
                "--- choose ship to address ---");
            if (dto.SalesOrderID != 0 && dto.ShipToAddressID != null)
            {
                //there is an entry, so set the selected value to that
                dto.ShipToOptions.SetSelectedValue(((int)dto.ShipToAddressID).ToString("D"));
            }

            dto.BillToOptions.SetupDropDownListContent(
                getPossibleAddresses.Select(
                    y =>
                    new KeyValuePair <string, string>(ListCustomerAddressDto.FormCustomerAddressFormatted(y),
                                                      y.AddressID.ToString("D"))),
                "--- choose bill to address ---");
            if (dto.SalesOrderID != 0 && dto.BillToAddressID != null)
            {
                //there is an entry, so set the selected value to that
                dto.BillToOptions.SetSelectedValue(((int)dto.BillToAddressID).ToString("D"));
            }
        }
        /// <summary>
        /// This provides the IQueryable command to get a list of TEntity, but projected to TDto.
        /// Can be overridden if standard AutoMapping isn't good enough, or return null if not supported
        /// </summary>
        /// <returns></returns>
        protected internal virtual IQueryable <TDto> ListQueryUntracked(IGenericServicesDbContext context)
        {
            var query = GetDataUntracked(context).ProjectTo <TDto>(GenericServicesConfig.AutoMapperConfigs[CreateDictionaryKey <TEntity, TDto>()]);

            //We check if we need to decompile the LINQ expression so that any computed properties in the class are filled in properly
            return(ApplyDecompileIfNeeded(query));
        }
Example #6
0
        private static List <PropertyInfo> FindKeys(Type type, IGenericServicesDbContext context)
        {
            var metadata = ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace;

            // Get the part of the model that contains info about the actual CLR types
            var objectItemCollection = ((ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace));

            // Get the entity type from the model that maps to the CLR type
            var entityType = metadata
                             .GetItems <EntityType>(DataSpace.OSpace)
                             .SingleOrDefault(e => objectItemCollection.GetClrType(e) == type);

            if (entityType == null)
            {
                throw new InvalidOperationException("This method expects a entity class. Did you provide a DTO by mistake?");
            }

            var keyProperties = entityType.KeyProperties.Select(x => type.GetProperty(x.Name)).ToList();

            if (!keyProperties.Any())
            {
                throw new MissingPrimaryKeyException(string.Format("Failed to find a EF primary key in type {0}", type.Name));
            }
            if (keyProperties.Any(x => x == null))
            {
                throw new NullReferenceException(string.Format("Failed to find key property by name in type {0}", type.Name));
            }

            return(keyProperties);
        }
Example #7
0
        /// <summary>
        /// This is used in a create. It copies only the properties in TDto that have public setter into the TEntity.
        /// You can override this if you need a more complex copy
        /// Note: If SupportedFunctions has the flag ValidateonCopyDtoToData then it validates the data (used by Action methods)
        /// </summary>
        /// <param name="context"></param>
        /// <param name="source"></param>
        /// <returns>status which, if Valid, has new TEntity with data from DTO copied in</returns>
        internal protected virtual ISuccessOrErrors <TEntity> CreateDataFromDto(IGenericServicesDbContext context, TDto source)
        {
            var result = new TEntity();

            Mapper.Map(source, result);
            return(new SuccessOrErrors <TEntity>(result, "Successful copy of data"));
        }
        /// <summary>
        /// This sets up the dropdownlist for the possible bloggers and the MultiSelectList of tags
        /// </summary>
        /// <param name="context"></param>
        /// <param name="dto"></param>
        protected override async Task SetupSecondaryDataAsync(IGenericServicesDbContext context, DetailPostDtoAsync dto)
        {
            var bloggers = await context.Set <Blog>().ToListAsync();

            dto.Bloggers.SetupDropDownListContent(bloggers.Select(x => new KeyValuePair <string, string>(x.Name, x.BlogId.ToString("D"))),
                                                  "--- choose blogger ---");
            if (dto.PostId != 0)
            {
                //there is an entry, so set the selected value to that
                dto.Bloggers.SetSelectedValue(dto.BlogId.ToString("D"));
            }

            List <KeyValuePair <string, int> > preselectedTags;

            if (dto.PostId == 0)
            {
                //create, so just produce empty list
                preselectedTags = new List <KeyValuePair <string, int> >();
            }
            else
            {
                var tags = await context.Set <Tag>()
                           .Where(x => x.Posts.Any(y => y.PostId == dto.PostId))
                           .Select(x => new { Key = x.Name, Value = x.TagId })
                           .ToListAsync();

                preselectedTags = tags.Select(x => new KeyValuePair <string, int>(x.Key, x.Value))
                                  .ToList();
            }

            dto.UserChosenTags.SetupMultiSelectList(
                context.Set <Tag>().ToList().Select(x => new KeyValuePair <string, int>(x.Name, x.TagId)), preselectedTags);
        }
Example #9
0
        private async Task <ISuccessOrErrors> DeleteBloggerWithPost(IGenericServicesDbContext db, Post post)
        {
            var blogger = await db.Set <Blog>().FindAsync(post.BlogId);

            db.Set <Blog>().Remove(blogger);
            return(SuccessOrErrors.Success("It was fine."));
        }
Example #10
0
        //---------------------------------------------------
        //private helpers

        private ISuccessOrErrors SetupRestOfDto(IGenericServicesDbContext context, Post post = null)
        {
            var db = context as SampleWebAppDb;

            if (db == null)
            {
                throw new NullReferenceException("The IDbContextWithValidation must be linked to TemplateWebAppDb.");
            }

            var status = SuccessOrErrors.Success("OK if no errors set");

            //now we sort out the blogger
            var errMsg = SetBloggerIdFromDropDownList(db);

            if (errMsg != null)
            {
                status.AddNamedParameterError("Bloggers", errMsg);
            }

            //now we sort out the tags
            errMsg = ChangeTagsBasedOnMultiSelectList(db, post);
            if (errMsg != null)
            {
                status.AddNamedParameterError("UserChosenTags", errMsg);
            }

            return(status);
        }
Example #11
0
        /// <summary>
        /// This sets up the dropdownlist for the possible bloggers and the MultiSelectList of tags
        /// </summary>
        /// <param name="context"></param>
        /// <param name="dto"></param>
        protected override void SetupSecondaryData(IGenericServicesDbContext context, DetailPostDto dto)
        {
            dto.Bloggers.SetupDropDownListContent(
                context.Set <Blog>()
                .ToList()
                .Select(x => new KeyValuePair <string, string>(x.Name, x.BlogId.ToString("D"))),
                "--- choose blogger ---");
            if (dto.PostId != 0)
            {
                //there is an entry, so set the selected value to that
                dto.Bloggers.SetSelectedValue(dto.BlogId.ToString("D"));
            }

            var preselectedTags = dto.PostId == 0
                ? new List <KeyValuePair <string, int> >()
                : context.Set <Tag>()
                                  .Where(x => x.Posts.Any(y => y.PostId == dto.PostId))
                                  .Select(x => new { Key = x.Name, Value = x.TagId })
                                  .ToList()
                                  .Select(x => new KeyValuePair <string, int>(x.Key, x.Value))
                                  .ToList();

            dto.UserChosenTags.SetupMultiSelectList(
                context.Set <Tag>().ToList().Select(x => new KeyValuePair <string, int>(x.Name, x.TagId)), preselectedTags);
        }
Example #12
0
        /// <summary>
        /// This provides the IQueryable command to get a list of TEntity, but projected to TDto.
        /// Can be overridden if standard AutoMapping isn't good enough, or return null if not supported
        /// </summary>
        /// <returns></returns>
        internal protected virtual IQueryable <TDto> ListQueryUntracked(IGenericServicesDbContext context)
        {
            var query = GetDataUntracked(context).Project().To <TDto>();

            //We check if we need to decompile the LINQ expression so that any computed properties in the class are filled in properly
            return(ApplyDecompileIfNeeded(query));
        }
Example #13
0
        protected override ISuccessOrErrors UpdateDataFromDto(IGenericServicesDbContext context, DetailPostDto source, Post destination)
        {
            var status = SetupRestOfDto(context, destination);

            return(status.IsValid
                ? base.UpdateDataFromDto(context, this, destination)
                : status);
        }
        protected override async Task <ISuccessOrErrors> UpdateDataFromDtoAsync(IGenericServicesDbContext context, DetailPostDtoAsync source, Post destination)
        {
            var status = await SetupRestOfDto(context, destination);

            return(status.IsValid
                ? await base.UpdateDataFromDtoAsync(context, this, destination)
                : status);
        }
Example #15
0
        /// <summary>
        /// This copies an existing TEntity into a new the dto using a Lambda expression to define the where clause
        /// It copies TEntity properties into all TDto properties that have accessable setters, i.e. not private
        /// </summary>
        /// <returns>status. If Valid then dto, otherwise null</returns>
        internal protected virtual async Task <ISuccessOrErrors <TDto> > DetailDtoFromDataInAsync(
            IGenericServicesDbContext context, Expression <Func <TEntity, bool> > predicate)
        {
            var query = GetDataUntracked(context).Where(predicate).Project().To <TDto>();

            //We check if we need to decompile the LINQ expression so that any computed properties in the class are filled in properly
            return(await ApplyDecompileIfNeeded(query).RealiseSingleWithErrorCheckingAsync());
        }
Example #16
0
        protected override ISuccessOrErrors <Post> CreateDataFromDto(IGenericServicesDbContext context, DetailPostDto source)
        {
            var status = SetupRestOfDto(context);

            return(status.IsValid
                ? base.CreateDataFromDto(context, this)
                : SuccessOrErrors <Post> .ConvertNonResultStatus(status));
        }
        /// <summary>
        /// This is used in a create. It copies only the properties in TDto that have public setter into the TEntity.
        /// You can override this if you need a more complex copy
        /// </summary>
        /// <param name="context"></param>
        /// <param name="source"></param>
        /// <returns>status which, if Valid, has new TEntity with data from DTO copied in</returns>
        protected internal virtual ISuccessOrErrors <TEntity> CreateDataFromDto(IGenericServicesDbContext context, TDto source)
        {
            var result = new TEntity();
            var mapper = GenericServicesConfig.AutoMapperConfigs[CreateDictionaryKey <TDto, TEntity>()].CreateMapper();

            mapper.Map(source, result);
            return(new SuccessOrErrors <TEntity>(result, "Successful copy of data"));
        }
        /// <summary>
        /// This copies an existing TEntity into a new dto using a Lambda expression to define the where clause
        /// It copies TEntity properties into all TDto properties that have accessable setters, i.e. not private
        /// </summary>
        /// <returns>status. If valid result is dto. Otherwise null</returns>
        protected internal virtual ISuccessOrErrors <TDto> DetailDtoFromDataIn(IGenericServicesDbContext context,
                                                                               Expression <Func <TEntity, bool> > predicate)
        {
            var query = GetDataUntracked(context).Where(predicate).ProjectTo <TDto>(
                GenericServicesConfig.AutoMapperConfigs[CreateDictionaryKey <TEntity, TDto>()]);

            //We check if we need to decompile the LINQ expression so that any computed properties in the class are filled in properly
            return(ApplyDecompileIfNeeded(query).RealiseSingleWithErrorChecking());
        }
        /// <summary>
        /// This is used to update the SalesOrderHeader total when a line item is deleted
        /// </summary>
        /// <param name="db"></param>
        /// <param name="lineItemBeingDeleted"></param>
        /// <returns></returns>
        public static ISuccessOrErrors UpdateSalesOrderHeader(IGenericServicesDbContext db, SalesOrderDetail lineItemBeingDeleted)
        {
            var salesOrderHeader = db.Set <SalesOrderHeader>().Include(x => x.SalesOrderDetails).Single(x => x.SalesOrderID == lineItemBeingDeleted.SalesOrderID);

            salesOrderHeader.SubTotal =
                salesOrderHeader.SalesOrderDetails.Where(
                    x => x.SalesOrderDetailID != lineItemBeingDeleted.SalesOrderDetailID).Sum(x => x.LineTotal);

            return(SuccessOrErrors.Success("Removed Ok"));
        }
        /// <summary>
        /// This is used to update the SalesOrderHeader total when a line item is deleted
        /// </summary>
        /// <param name="db"></param>
        /// <param name="lineItemBeingDeleted"></param>
        /// <returns></returns>
        public static ISuccessOrErrors UpdateSalesOrderHeader(IGenericServicesDbContext db, SalesOrderDetail lineItemBeingDeleted)
        {
            var salesOrderHeader = db.Set<SalesOrderHeader>().Include(x => x.SalesOrderDetails).Single(x => x.SalesOrderID == lineItemBeingDeleted.SalesOrderID);

            salesOrderHeader.SubTotal =
                salesOrderHeader.SalesOrderDetails.Where(
                    x => x.SalesOrderDetailID != lineItemBeingDeleted.SalesOrderDetailID).Sum(x => x.LineTotal);

            return SuccessOrErrors.Success("Removed Ok");
        }
Example #21
0
        /// <summary>
        /// This is called on create. We override it to get at the pasword hash/salt
        /// </summary>
        /// <param name="context"></param>
        /// <param name="source"></param>
        /// <returns></returns>
        protected override ISuccessOrErrors <Customer> CreateDataFromDto(IGenericServicesDbContext context, CrudCustomerDto source)
        {
            //We need to initialise the username and password

            var data = base.CreateDataFromDto(context, source);

            data.Result.PasswordHash = "empty";
            data.Result.PasswordSalt = "empty";

            return(data);
        }
        public static ISuccessOrErrors DeleteAssociatedAddress(IGenericServicesDbContext db, CustomerAddress customerAddress)
        {
            var address = db.Set<Address>().Find(customerAddress.AddressID);

            if (address == null)
                return
                    new SuccessOrErrors().AddSingleError(
                        "Could not delete the associated entry as it was not in the database. Could it have been deleted by someone else?");

            db.Set<Address>().Remove(address);
            return SuccessOrErrors.Success("Removed Ok");
        }
        protected internal override ISuccessOrErrors UpdateDataFromDto(IGenericServicesDbContext context, TDto source, TEntity destination)
        {
            using (new LogStartStop(this))
            {
                if (_whereToFail.HasFlag(InstrumentedOpFlags.FailOnUpdateDataFromDto))
                {
                    return(new SuccessOrErrors().AddSingleError("Flag was set to fail in UpdateDataFromDto."));
                }

                return(base.UpdateDataFromDto(context, source, destination));
            }
        }
        protected internal override ISuccessOrErrors <TEntity> CreateDataFromDto(IGenericServicesDbContext context, TDto source)
        {
            using (new LogStartStop(this))
            {
                if (_whereToFail.HasFlag(InstrumentedOpFlags.FailOnCreateDataFromDto))
                {
                    return(SuccessOrErrors <TEntity> .ConvertNonResultStatus(new SuccessOrErrors().AddSingleError("Flag was set to fail in CreateDataFromDto.")));
                }

                return(base.CreateDataFromDto(context, source));
            }
        }
Example #25
0
        protected override ISuccessOrErrors UpdateDataFromDto(IGenericServicesDbContext context, DetailPostDto source, Post destination)
        {
            var status = SetupRestOfDto(context, destination);

            if (status.IsValid)
            {
                //now we copy the items to the right place
                status = base.UpdateDataFromDto(context, this, destination);
            }

            return(status);
        }
        //This code is the second attempt at improving the SQL query for Customers
        //It uses the from ... in format of LINQ which allows a let assignment in it.
        //This produces a better SQL query

        protected override IQueryable <ListCustomerVer2Dto> ListQueryUntracked(IGenericServicesDbContext context)
        {
            return(from x in context.Set <Customer>()
                   let hasBoughtBefore = x.SalesOrderHeaders.Any()
                                         select new ListCustomerVer2Dto
            {
                CustomerID = x.CustomerID,
                CompanyName = x.CompanyName,
                FullName = x.Title + (x.Title == null ? "" : " ") + x.FirstName + " " + x.LastName + " " + x.Suffix,
                HasBoughtBefore = hasBoughtBefore,
                TotalAllOrders = hasBoughtBefore ? x.SalesOrderHeaders.Sum(y => y.TotalDue) : 0
            });
        }
Example #27
0
        //---------------------------------------------------------------
        //protected methods

        /// <summary>
        /// This gets the key values from this DTO in the correct order. Used in FindItemTrackedForUpdate sync/async
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        protected object[] GetKeyValues(IGenericServicesDbContext context)
        {
            var efkeyProperties = context.GetKeyProperties <TEntity>().ToArray();
            var dtoProperties   = typeof(TDto).GetProperties(BindingFlags.Public | BindingFlags.Instance);
            var keysInOrder     = efkeyProperties.Select(x => dtoProperties.SingleOrDefault(y => y.Name == x.Name && y.PropertyType == x.PropertyType)).ToArray();

            if (keysInOrder.Any(x => x == null))
            {
                throw new MissingPrimaryKeyException("The dto must contain all the key(s) properties from the data class.");
            }

            return(keysInOrder.Select(x => x.GetValue(this)).ToArray());
        }
        protected override ISuccessOrErrors UpdateDataFromDto(IGenericServicesDbContext context, CrudSalesOrderDto source,
                                                              SalesOrderHeader destination)
        {
            var status = SetupRestOfDto(context, source);

            if (status.IsValid)
            {
                //now we copy the items to the right place
                status = base.UpdateDataFromDto(context, source, destination);
            }

            return(status);
        }
Example #29
0
        public static ISuccessOrErrors DeleteAssociatedAddress(IGenericServicesDbContext db, CustomerAddress customerAddress)
        {
            var address = db.Set <Address>().Find(customerAddress.AddressID);

            if (address == null)
            {
                return
                    (new SuccessOrErrors().AddSingleError(
                         "Could not delete the associated entry as it was not in the database. Could it have been deleted by someone else?"));
            }

            db.Set <Address>().Remove(address);
            return(SuccessOrErrors.Success("Removed Ok"));
        }
        //---------------------------------------------------------------
        //protected methods

        /// <summary>
        /// This gets the key values from this DTO. Used in FindItemTrackedForUpdate sync/async
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        protected object[] GetKeyValues(IGenericServicesDbContext context)
        {
            var efkeyPropertyNames = context.GetKeyProperties <TEntity>().ToArray();

            var dtoKeyProperies = typeof(TDto).GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                  .Where(x => efkeyPropertyNames.Any(y => y.Name == x.Name && y.PropertyType == x.PropertyType)).ToArray();

            if (efkeyPropertyNames.Length != dtoKeyProperies.Length)
            {
                throw new MissingPrimaryKeyException("The dto must contain the key(s) properties from the data class.");
            }

            return(dtoKeyProperies.Select(x => x.GetValue(this)).ToArray());
        }
        protected override ISuccessOrErrors <SalesOrderDetail> CreateDataFromDto(IGenericServicesDbContext context, CreateLineItemDto source)
        {
            var status = base.CreateDataFromDto(context, source);

            if (!status.IsValid)
            {
                return(status);
            }

            //we read the list price from the products
            status.Result.UnitPrice         = context.Set <Product>().Single(x => x.ProductID == source.ProductID).ListPrice;
            status.Result.UnitPriceDiscount = 0;

            return(status);
        }
Example #32
0
        //----------------------------------------------------------------------
        //non-overridable internal methods

        /// <summary>
        /// This copies back the keys from a newly created entity into the dto as long as there are matching properties in the Dto
        /// </summary>
        /// <param name="context"></param>
        /// <param name="newEntity"></param>
        internal protected void AfterCreateCopyBackKeysToDtoIfPresent(IGenericServicesDbContext context, TEntity newEntity)
        {
            var dtoKeyProperies = typeof(TDto).GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (var entityKeys in context.GetKeyProperties <TEntity>())
            {
                var dtoMatchingProperty =
                    dtoKeyProperies.SingleOrDefault(
                        x => x.Name == entityKeys.Name && x.PropertyType == entityKeys.PropertyType);
                if (dtoMatchingProperty == null)
                {
                    continue;
                }

                dtoMatchingProperty.SetValue(this, entityKeys.GetValue(newEntity));
            }
        }
 private ISuccessOrErrors DeleteBloggerWithPost(IGenericServicesDbContext db, SimplePostDto post)
 {
     var blogger = db.Set<Blog>().SingleOrDefault(x => x.Name == post.BloggerName);
     db.Set<Blog>().Remove(blogger);
     return SuccessOrErrors.Success("It was fine.");
 }
 private async Task<ISuccessOrErrors> DeleteBloggerWithPost(IGenericServicesDbContext db, Post post)
 {
     var blogger = await db.Set<Blog>().FindAsync(post.BlogId);
     db.Set<Blog>().Remove(blogger);
     return SuccessOrErrors.Success("It was fine.");
 }
 private async Task<ISuccessOrErrors> FailDeleteRelationships(IGenericServicesDbContext db, Post post)
 {
     return new SuccessOrErrors().AddSingleError("I failed.");
 }
Example #36
0
 private static void RunCommand2(IGenericServicesDbContext db)
 {
     var service = new ListService(db);
     var list = service.GetAll<SimplePostDto>().ToList();
 }