/// <summary> /// This will soft delete the single entity. This may delete other dependent /// </summary> /// <param name="softDeleteThisEntity">Mustn't be null</param> /// <param name="callSaveChanges">Defaults to calling SaveChanges. If set to false, then you must call SaveChanges</param> /// <returns>Returns status. If not errors then Result return 1 to say it worked. Zero if error</returns> public async Task <IStatusGeneric <int> > SetSoftDeleteAsync(TInterface softDeleteThisEntity, bool callSaveChanges = true) { if (softDeleteThisEntity == null) { throw new ArgumentNullException(nameof(softDeleteThisEntity)); } _context.ThrowExceptionIfPrincipalOneToOne(softDeleteThisEntity); var status = new StatusGenericHandler <int>(); if (_config.GetSoftDeleteValue.Compile().Invoke(softDeleteThisEntity)) { return(status.AddError($"This entry is already {_config.TextSoftDeletedPastTense}.")); } _config.SetSoftDeleteValue(softDeleteThisEntity, true); if (callSaveChanges) { await _context.SaveChangesAsync(); } status.Message = $"Successfully {_config.TextSoftDeletedPastTense} this entry"; status.SetResult(1); //one changed return(status); }
/******************************************************************* #A This method returns a status with the created Order, which is null if there are no errors #B The PlaceOrderInDto contains a TandC bool and a collection of BookIds and number of books #C This status is used to gather and errors and, if no errors, return an Order #D These validate the user's input #E The _dbAccess contains the code to find each book - see listing 4.3 #F This method creates list of bookId and number of books - see end of listing 4.2 #G If any errors were found while checking each order line, then it returns the error status #H This calls the Order static factory. It is the Order's job to form the Order with LineItems #I Again, any errors will abort the Order and the errors returned #J The _dbAccess contains the code add the Order and call SaveChangesAsync #K Finally it returns a successful status with the created Order entity ****************************************************************/ private IStatusGeneric <List <OrderBookDto> > FormLineItemsWithErrorChecking (IEnumerable <OrderLineItem> lineItems, IDictionary <int, BookView> booksDict) { var status = new StatusGenericHandler <List <OrderBookDto> >(); var result = new List <OrderBookDto>(); foreach (var lineItem in lineItems) { if (!booksDict.ContainsKey(lineItem.BookId)) { throw new InvalidOperationException( $"An order failed because book, id = {lineItem.BookId} was missing."); } var bookView = booksDict[lineItem.BookId]; if (bookView.ActualPrice <= 0) { status.AddError($"Sorry, the book '{bookView.Title}' is not for sale."); } else { //Valid, so add to the order result.Add(new OrderBookDto(bookView, lineItem.NumBooks)); } } return(status.SetResult(result)); }
public static async Task <IStatusGeneric <RoleToPermissions> > CreateRoleWithPermissionsAsync( string roleName, string description, IEnumerable <Permission> permissionInRole, IAuthorizationRepository repository) { if (roleName == null) { throw new ArgumentNullException(nameof(roleName)); } if (repository == null) { throw new ArgumentNullException(nameof(repository)); } var status = new StatusGenericHandler <RoleToPermissions>(); RoleToPermissions roleToPermissions = await repository.GetRoleToPermissionAsync(roleName); if (roleToPermissions != null) { status.AddError("That role already exists"); return(status); } return(status.SetResult(new RoleToPermissions(roleName, description, permissionInRole))); }
private IStatusGeneric <int> ReturnSuccessFullResult(CascadeSoftDelWhatDoing whatDoing, int numFound) { var status = new StatusGenericHandler <int>(); status.SetResult(numFound); switch (whatDoing) { case CascadeSoftDelWhatDoing.SoftDelete: status.Message = FormMessage("soft deleted", numFound); break; case CascadeSoftDelWhatDoing.ResetSoftDelete: status.Message = FormMessage("recovered", numFound); break; case CascadeSoftDelWhatDoing.CheckWhatWillDelete: status.Message = numFound == 0 ? "No entries will be hard deleted" : $"Are you sure you want to hard delete this entity{DependentsSuffix(numFound)}"; break; case CascadeSoftDelWhatDoing.HardDeleteSoftDeleted: status.Message = FormMessage("hard deleted", numFound); break; default: throw new ArgumentOutOfRangeException(); } return(status); }
/// <summary> /// This converts the <see cref="ActionResult{WebApiMessageAndResult{T}}"/> created by <see cref="CreateResponse"/> into a GenericServices.IStatusGeneric /// </summary> /// <param name="actionResult"></param> /// <returns>a status which is similar to the original status (errors might not be in the exact same form)</returns> public static IStatusGeneric <T> CopyToStatus <T>(this ActionResult <WebApiMessageAndResult <T> > actionResult) { var testStatus = new StatusGenericHandler <T>(); var objResult = (actionResult.Result as ObjectResult); if (objResult == null) { throw new NullReferenceException("Could not cast the response to ObjectResult"); } var errorPart = objResult as BadRequestObjectResult; if (errorPart != null) { //It has errors, so copy errors to status testStatus.AddValidationResults(ExtractErrors(errorPart)); return(testStatus); } var decodedValue = objResult.Value as WebApiMessageAndResult <T>; if (decodedValue == null) { throw new NullReferenceException($"Could not cast the response value to WebApiMessageAndResult<{typeof(T).Name}>"); } testStatus.Message = decodedValue.Message; testStatus.SetResult(decodedValue.Results); return(testStatus); }
private IStatusGeneric <int> //#A CallSaveChangesWithExceptionHandler (DbContext context, Func <int> callBaseSaveChanges) //#B { var status = new StatusGenericHandler <int>(); //#C do //#D { try { int numUpdated = callBaseSaveChanges(); //#E status.SetResult(numUpdated); //#F break; //#F } catch (Exception e) //#G { IStatusGeneric handlerStatus = null; //#H if (handlerStatus == null) //#I { throw; //#I } status.CombineStatuses(handlerStatus); //#J } } while (status.IsValid); //#K return(status); //#L }
public static IStatusGeneric <UserToRole> AddRoleToUser(string userId, string roleName, ExtraAuthorizeDbContext context) { if (userId == null) { throw new ArgumentNullException(nameof(userId)); } if (roleName == null) { throw new ArgumentNullException(nameof(roleName)); } var status = new StatusGenericHandler <UserToRole>(); if (context.Find <UserToRole>(userId, roleName) != null) { status.AddError($"The user already has the Role '{roleName}'."); return(status); } var roleToAdd = context.Find <RoleToPermissions>(roleName); if (roleToAdd == null) { status.AddError($"I could not find the Role '{roleName}'."); return(status); } return(status.SetResult(new UserToRole(userId, roleToAdd))); }
/// <summary> /// This runs the events before and after the base SaveChangesAsync method is run /// </summary> /// <param name="context">The current DbContext</param> /// <param name="getTrackedEntities">A function to get the tracked entities</param> /// <param name="callBaseSaveChangesAsync">A function that is linked to the base SaveChangesAsync in your DbContext</param> /// <returns>Returns the status with the numUpdated number from SaveChanges</returns> public async Task <IStatusGeneric <int> > RunEventsBeforeAfterSaveChangesAsync(DbContext context, Func <IEnumerable <EntityEntry <EntityEvents> > > getTrackedEntities, Func <Task <int> > callBaseSaveChangesAsync) { var status = new StatusGenericHandler <int>(); status.CombineStatuses(RunBeforeSaveChangesEvents(getTrackedEntities)); if (!status.IsValid) { return(status); } //Call SaveChangesAsync with catch for exception handler do { try { status.SetResult(await callBaseSaveChangesAsync.Invoke().ConfigureAwait(false)); break; //This breaks out of the do/while } catch (Exception e) { var exceptionStatus = _config.SaveChangesExceptionHandler?.Invoke(e, context); if (exceptionStatus == null) { //This means the SaveChangesExceptionHandler doesn't cover this type of Concurrency Exception throw; } //SaveChangesExceptionHandler ran, so combine its error into the outer status status.CombineStatuses(exceptionStatus); } //If the SaveChangesExceptionHandler fixed the problem then we call SaveChanges again, but with the same exception catching. } while (status.IsValid); RunAfterSaveChangesEvents(getTrackedEntities); return(status); }
//---------------------------------------------- //create methods /// <summary> /// This creates a Sale entry, and also update the ShopStock number in stock /// </summary> /// <param name="numBought"></param> /// <param name="shopStockId"></param> /// <param name="context"></param> /// <returns></returns> public static IStatusGeneric <ShopSale> CreateSellAndUpdateStock(int numBought, int shopStockId, DbContext context) { if (numBought < 0) { throw new ArgumentException("must be positive", nameof(numBought)); } var status = new StatusGenericHandler <ShopSale>(); var stock = context.Find <ShopStock>(shopStockId); if (stock == null) { status.AddError("Could not find the stock item you requested."); return(status); } stock.NumInStock = stock.NumInStock - numBought; if (stock.NumInStock < 0) { status.AddError("There are not enough items of that product to sell."); return(status); } var sale = new ShopSale(numBought, null, shopStockId); return(status.SetResult(sale)); }
public async Task <IStatusGeneric <Order> > //#A CreateOrderAndSaveAsync(PlaceOrderInDto dto) //#B { var status = new StatusGenericHandler <Order>(); //#C if (!dto.AcceptTAndCs) //#D { return(status.AddError("You must accept the T&Cs to place an order.")); } if (!dto.LineItems.Any()) //#D { return(status.AddError("No items in your basket.")); } var booksDict = await _dbAccess //#E .FindBooksByIdsAsync //#E (dto.LineItems.Select(x => x.BookId)); //#E var linesStatus = FormLineItemsWithErrorChecking //#F (dto.LineItems, booksDict); //#F if (status.CombineStatuses(linesStatus).HasErrors) //#G { return(status); //#G } var orderStatus = Order.CreateOrder( //#H dto.UserId, linesStatus.Result); //#H if (status.CombineStatuses(orderStatus).HasErrors) //#I { return(status); //#I } await _dbAccess.AddAndSave(orderStatus.Result); //#J return(status.SetResult(orderStatus.Result)); //#K }
/// <summary> /// This will soft delete the single entity. This may delete other dependent /// </summary> /// <param name="softDeleteThisEntity">Mustn't be null</param> /// <param name="callSaveChanges">Defaults to calling SaveChanges. If set to false, then you must call SaveChanges</param> /// <returns>Returns status. If not errors then Result return 1 to say it worked. Zero if error</returns> public async Task <IStatusGeneric <int> > SetSoftDeleteAsync(TInterface softDeleteThisEntity, bool callSaveChanges = true) { if (softDeleteThisEntity == null) { throw new ArgumentNullException(nameof(softDeleteThisEntity)); } var keys = _context.Entry(softDeleteThisEntity).Metadata.GetForeignKeys(); if (!keys.All(x => x.DependentToPrincipal?.IsCollection == true || x.PrincipalToDependent?.IsCollection == true)) { //This it is a one-to-one entity - setting a one-to-one as soft deleted causes problems when you try to create a replacement throw new InvalidOperationException("You cannot soft delete a one-to-one relationship. " + "It causes problems if you try to create a new version."); } var status = new StatusGenericHandler <int>(); if (_config.GetSoftDeleteValue.Compile().Invoke(softDeleteThisEntity)) { return(status.AddError($"This entry is already {_config.TextSoftDeletedPastTense}.")); } _config.SetSoftDeleteValue(softDeleteThisEntity, true); if (callSaveChanges) { await _context.SaveChangesAsync(); } status.Message = $"Successfully {_config.TextSoftDeletedPastTense} this entry"; status.SetResult(1); //one changed return(status); }
/// <summary> /// This hard deletes (i.e. calls EF Core's Remove method) for this entity ONLY if it first been soft deleted. /// This will delete the entity and possibly delete other dependent entities. /// </summary> /// <typeparam name="TEntity"></typeparam> /// <param name="hardDeleteThisEntity">The entity to delete</param> /// <param name="callSaveChanges">Defaults to calling SaveChanges. If set to false, then you must call SaveChanges yourself</param> /// <returns>The number of entities that were deleted. This will include any dependent entities that that had a cascade delete behaviour</returns> public async Task <IStatusGeneric <int> > HardDeleteSoftDeletedEntryAsync <TEntity>(TEntity hardDeleteThisEntity, bool callSaveChanges = true) where TEntity : class, TInterface { if (hardDeleteThisEntity == null) { throw new ArgumentNullException(nameof(hardDeleteThisEntity)); } var status = new StatusGenericHandler <int>(); if (!_config.GetSoftDeleteValue.Compile().Invoke(hardDeleteThisEntity)) { return(status.AddError($"This entry isn't {_config.TextSoftDeletedPastTense}.")); } _context.Remove(hardDeleteThisEntity); var numDeleted = 1; if (callSaveChanges) { numDeleted = await _context.SaveChangesAsync(); } status.Message = $"Successfully {_config.TextHardDeletedPastTense} this entry"; status.SetResult(numDeleted); return(status); }
public static IStatusGeneric<Target1> Create(int myInt, string myString) { var status = new StatusGenericHandler<Target1> { Message = "Static" }; return status.SetResult(new Target1(myInt, myString)); }
} //Needed by EF Core public static IStatusGeneric <Book> CreateBook( string title, DateTime publishedOn, bool estimatedDate, string publisher, decimal price, string imageUrl, ICollection <Author> authors, ICollection <Tag> tags = null) { var status = new StatusGenericHandler <Book>(); if (string.IsNullOrWhiteSpace(title)) { status.AddError( "The book title cannot be empty."); } var book = new Book { Title = title, PublishedOn = publishedOn, EstimatedDate = estimatedDate, Publisher = publisher, OrgPrice = price, ActualPrice = price, ImageUrl = imageUrl, //We need to initialise the AuthorsOrdered string when the entry is created //NOTE: We must NOT initialise the ReviewsCount and the ReviewsAverageVotes as they default to zero AuthorsOrdered = string.Join(", ", authors.Select(x => x.Name)), _tags = tags != null ? new HashSet <Tag>(tags) : new HashSet <Tag>(), _reviews = new HashSet <Review>() //We add an empty list on create. I allows reviews to be added when building test data }; if (authors == null) { throw new ArgumentNullException(nameof(authors)); } byte order = 0; book._authorsLink = new HashSet <BookAuthor>( authors.Select(a => new BookAuthor(book, a, order++))); if (!book._authorsLink.Any()) { status.AddError( "You must have at least one Author for a book."); } if (status.IsValid) { book.AddEvent(new BookChangedEvent(BookChangeTypes.Added), EventToSend.DuringSave); } return(status.SetResult(book)); }
public static IStatusGeneric <object> RunMethodOrCtorViaLinq(MethodCtorMatch ctorOrMethod, dynamic dto, List <PropertyMatch> propertyMatches, DbContext context) { var result = new StatusGenericHandler <object>(); if (ctorOrMethod.Constructor != null) { var ctor = CallConstructor(ctorOrMethod.Constructor, dto.GetType(), propertyMatches); return(propertyMatches.Any(x => x.MatchSource == MatchSources.DbContext) ? result.SetResult(ctor(dto, context)) : result.SetResult(ctor(dto))); } //Otherwise its static method var staticFunc = CallStaticCreator(ctorOrMethod.Method, dto.GetType(), propertyMatches); return(propertyMatches.Any(x => x.MatchSource == MatchSources.DbContext) ? staticFunc(dto, context) : staticFunc(dto)); }
public void TestGenericStatusGeneicSetResultOk() { //SETUP //ATTEMPT var status = new StatusGenericHandler <string>(); status.SetResult("Hello world"); //VERIFY status.IsValid.ShouldBeTrue(); status.Result.ShouldEqual("Hello world"); }
public static IStatusGeneric <DecodedDto> GetOrCreateDtoInfo(this Type classType, DecodedEntityClass entityInfo, IGenericServicesConfig publicConfig, PerDtoConfig perDtoConfig) { var status = new StatusGenericHandler <DecodedDto>(); if (classType.IsPublic || classType.IsNestedPublic) { return(status.SetResult(DecodedDtoCache.GetOrAdd(classType, type => new DecodedDto(classType, entityInfo, publicConfig, perDtoConfig)))); } status.AddError($"Sorry, but the DTO/ViewModel class '{classType.Name}' must be public for GenericServices to work."); return(status); }
public static IStatusGeneric <RoleToPermissions> CreateRoleWithPermissions(string roleName, string description, ICollection <Permissions> permissionInRole, ExtraAuthorizeDbContext context) { var status = new StatusGenericHandler <RoleToPermissions>(); if (context.Find <RoleToPermissions>(roleName) != null) { status.AddError("That role already exists"); return(status); } return(status.SetResult(new RoleToPermissions(roleName, description, permissionInRole))); }
public void TestGenericStatusGeneicSetResultThenErrorOk() { //SETUP //ATTEMPT var status = new StatusGenericHandler <string>(); status.SetResult("Hello world"); status.AddError("This is an error."); //VERIFY status.IsValid.ShouldBeFalse(); status.Result.ShouldEqual(null); }
public IStatusGeneric <string> CheckUpdateBookCacheProperties() { var status = new StatusGenericHandler <string>(); var errorStrings = new StringBuilder(); var numBooksChecked = 0; var numErrors = 0; foreach (var book in _context.Books .Include(x => x.Reviews) .Include(x => x.AuthorsLink).ThenInclude(x => x.Author)) { var error = Errors.None; numBooksChecked++; var authorsOrdered = book.FormAuthorOrderedString(); var reviewsCount = book.Reviews.Count(); var reviewsAverageVotes = reviewsCount == 0 ? 0 : book.Reviews.Sum(x => x.NumStars) / (double)book.ReviewsCount; if (authorsOrdered != book.AuthorsOrdered) { book.AuthorsOrdered = authorsOrdered; error = Errors.AuthorsWrong; } if (reviewsCount != book.ReviewsCount || reviewsAverageVotes != book.ReviewsAverageVotes) { book.ReviewsCount = reviewsCount; book.ReviewsAverageVotes = reviewsAverageVotes; error |= Errors.ReviewWrong; } if (error != Errors.None) { errorStrings.AppendLine($"Book: {book.Title} had the following errors: {error.ToString()}"); numErrors++; } } if (numErrors > 0) { _context.SaveChanges(); } status.SetResult(errorStrings.ToString()); status.Message = numErrors == 0 ? $"Processed {numBooksChecked} and no cache errors found" : $"Processed {numBooksChecked} books and {numErrors} errors found. See returned string for details"; return(status); }
public static IStatusGeneric <DddStaticCreateEntity> Create(int myInt, string myString) { var status = new StatusGenericHandler <DddStaticCreateEntity>(); var result = new DddStaticCreateEntity { MyInt = myInt, MyString = myString, }; if (myString == null) { status.AddError("The string should not be null."); } return(status.SetResult(result)); //This will return null if there are errors }
public IStatusGeneric <string> StatusGenericNumReturnString(int i) { var status = new StatusGenericHandler <string>(); //add error and return immediately if (i <= 0) { return(status.AddError("input must be positive", nameof(i))); } //This sets the Result property in the generic status status.SetResult(i.ToString()); //If there are errors then the Result is set to the default value for generic type return(status); }
public static IStatusGeneric <Book> CreateBook(string title, string description, DateTime publishedOn, string publisher, decimal price, string imageUrl, ICollection <Author> authors, ICollection <Tag> tags = null) { var status = new StatusGenericHandler <Book>(); if (string.IsNullOrWhiteSpace(title)) { status.AddError("The book title cannot be empty."); } var book = new Book { Title = title, Description = description, PublishedOn = publishedOn, Publisher = publisher, ActualPrice = price, OrgPrice = price, ImageUrl = imageUrl, _tags = tags != null ? new HashSet <Tag>(tags) : new HashSet <Tag>(), _reviews = new HashSet <Review>() //We add an empty list on create. I allows reviews to be added when building test data }; if (authors == null) { throw new ArgumentNullException(nameof(authors)); } byte order = 0; book._authorsLink = new HashSet <BookAuthor>(authors.Select(a => new BookAuthor(book, a, order++))); if (!book._authorsLink.Any()) { status.AddError("You must have at least one Author for a book."); } return(status.SetResult(book)); }
//---------------------------------------------- public static IStatusGeneric <BookWithEvents> CreateBook(string title, string description, DateTime publishedOn, string publisher, decimal price, string imageUrl, ICollection <AuthorWithEvents> authors) { var status = new StatusGenericHandler <BookWithEvents>(); if (string.IsNullOrWhiteSpace(title)) { status.AddError("The bookWithEvents title cannot be empty."); } var book = new BookWithEvents { BookId = Guid.NewGuid(), Title = title, Description = description, PublishedOn = publishedOn, Publisher = publisher, ActualPrice = price, OrgPrice = price, ImageUrl = imageUrl, //We need to initialise the AuthorsOrdered string when the entry is created AuthorsOrdered = string.Join(", ", authors.Select(x => x.Name)), //We don't need to initialise the ReviewsCount and the ReviewsAverageVotes as they default to zero _reviews = new HashSet <ReviewWithEvents>() //We add an empty list on create. I allows reviews to be added when building test data }; if (authors == null) { throw new ArgumentNullException(nameof(authors)); } byte order = 0; book._authorsLink = new HashSet <BookAuthorWithEvents>(authors.Select(a => new BookAuthorWithEvents(book, a, order++))); if (!book._authorsLink.Any()) { status.AddError("You must have at least one Author for a bookWithEvents."); } return(status.SetResult(book)); }
} //Needed by EF Core public static IStatusGeneric <Order> CreateOrder(string customerName, IEnumerable <OrderBooksDto> bookOrders) { var status = new StatusGenericHandler <Order>(); var order = new Order { CustomerName = customerName, Status = OrderStatuses.Created, OrderedUtc = DateTime.UtcNow }; byte lineNum = 1; order._lineItems = new HashSet <LineItem>(bookOrders .Select(x => new LineItem(x.numBooks, x.ChosenBook, lineNum++))); if (!order._lineItems.Any()) { status.AddError("No items in your basket."); } return(status.SetResult(order)); //don't worry, the Result will return default(T) if there are errors }
private async Task <IStatusGeneric <int> > CallSaveChangesWithExceptionHandlerAsync(DbContext context, Func <Task <int> > callBaseSaveChangesAsync) { var status = new StatusGenericHandler <int>(); do { try { context.ChangeTracker.AutoDetectChangesEnabled = false; status.SetResult(await callBaseSaveChangesAsync().ConfigureAwait(false)); break; //This breaks out of the do/while } catch (Exception e) { IStatusGeneric exceptionStatus = null; if (_config.ExceptionHandlerDictionary.TryGetValue(context.GetType(), out var exceptionHandler)) { exceptionStatus = exceptionHandler(e, context); } if (exceptionStatus == null) { //This means the SaveChangesExceptionHandler doesn't cover this type of Concurrency Exception throw; } //SaveChangesExceptionHandler ran, so combine its error into the outer status status.CombineStatuses(exceptionStatus); } finally { context.ChangeTracker.AutoDetectChangesEnabled = true; } //If the SaveChangesExceptionHandler fixed the problem then we call SaveChanges again, but with the same exception catching. } while (status.IsValid); return(status); }
public static IStatusGeneric <Order> CreateOrder //#A (Guid userId, //#B IEnumerable <OrderBookDto> bookOrders) //#C { var status = new StatusGenericHandler <Order>(); //#D var order = new Order //#E { //#E UserId = userId, //#E DateOrderedUtc = DateTime.UtcNow //#E }; //#E byte lineNum = 1; order._lineItems = new HashSet <LineItem>( //#F bookOrders //#F .Select(x => new LineItem(x, lineNum++))); //#F if (!order._lineItems.Any()) //#G { status.AddError("No items in your basket."); //#G } return(status.SetResult(order)); //#H }
/// <summary> /// This creates the order and, if successful clears the cookie /// </summary> /// <returns>Returns the OrderId, or zero if errors</returns> public async Task <IStatusGeneric <int> > PlaceOrderAndClearBasketAsync(bool acceptTAndCs) { var status = new StatusGenericHandler <int>(); var checkoutService = new CheckoutCookieService( _basketCookie.GetValue()); var bizStatus = await _placeOrder.CreateOrderAndSaveAsync( new PlaceOrderInDto(acceptTAndCs, checkoutService.UserId, checkoutService.LineItems)); if (status.CombineStatuses(bizStatus).HasErrors) { return(status); } //successful so clear the cookie line items checkoutService.ClearAllLineItems(); _basketCookie.AddOrUpdateCookie( checkoutService.EncodeForCookie()); return(status.SetResult(bizStatus.Result.OrderId)); }
public static async Task <IStatusGeneric <UserToRole> > AddRoleToUserAsync( string userId, string roleName, IAuthorizationRepository repository) { if (userId == null) { throw new ArgumentNullException(nameof(userId)); } if (roleName == null) { throw new ArgumentNullException(nameof(roleName)); } if (repository == null) { throw new ArgumentNullException(nameof(repository)); } var status = new StatusGenericHandler <UserToRole>(); UserToRole userToRole = await repository.GetUserToRoleAsync(userId, roleName); if (userToRole != null) { status.AddError($"The user already has the Role '{roleName}'."); return(status); } RoleToPermissions roleToAdd = await repository.GetRoleToPermissionAsync(roleName); if (roleToAdd == null) { status.AddError($"Could not find the Role '{roleName}'."); return(status); } return(status.SetResult(new UserToRole(userId, roleToAdd))); }
public static IStatusGeneric <Book> CreateBook( //#B string title, DateTime publishedOn, //#C decimal price, //#C ICollection <Author> authors) //#C { var status = new StatusGenericHandler <Book>(); //#D if (string.IsNullOrWhiteSpace(title)) //#E { status.AddError( //#E "The book title cannot be empty."); //#E } var book = new Book //#F { //#F Title = title, //#F PublishedOn = publishedOn, //#F OrgPrice = price, //#F ActualPrice = price, //#F }; if (authors == null) //#G { throw new ArgumentNullException(nameof(authors)); //#G } byte order = 0; //#H book._authorsLink = new HashSet <BookAuthor>( //#H authors.Select(a => //#H new BookAuthor(book, a, order++))); //#H if (!book._authorsLink.Any()) //#I { status.AddError( //#I "You must have at least one Author for a book."); //#I } return(status.SetResult(book)); //#J }