/// <summary> /// Unreserves a user's ad, doesn't refund reservations. /// </summary> /// <param name="id">Id of the Ad</param> /// <param name="userEmail">Email of the user</param> /// <exception cref="PostNotFoundException"></exception> /// <exception cref="UserNotFoundException"></exception> /// <exception cref="ArgumentException">If ad is not reserved or the author is different.</exception> public void UnreserveAd(string id, string userEmail) { Ad ad = GetAd(id); User user = UserControl.GetInstance().GetUser(userEmail); if (ad.ReservedBy == null) { throw new ArgumentException("Can not unreserve: Ad is not reserved."); } if (user.Id != ad.ReservedBy.Id) { throw new ArgumentException("Users can not unreserve other people's ads."); } var db = DbContextControl.GetNew(); //Get ad into context db.Ads.Attach(ad); db.Entry(ad).State = EntityState.Modified; ad.ReservedBy = null; db.SaveChanges(); }
public void DeleteAd(string id, string authorEmail) { var db = DbContextControl.GetNew(); Ad toDelete = new Ad { Id = id }; toDelete.Author = UserControl.GetInstance().GetUser(authorEmail);//TODO:change db.Ads.Attach(toDelete); Price price = toDelete.Price; if (price != null) { db.Prices.Attach(toDelete.Price); db.Prices.Remove(price); } var comments = db.Comments.Where(c => c.ReplyId == id); db.Comments.RemoveRange(comments); db.Ads.Remove(toDelete); //db.Entry(toDelete).State = EntityState.Deleted; db.SaveChanges(); }
public Comment PostComment(string adId, string content, string authorEmail) { var db = DbContextControl.GetNew(); var comment = new Comment { Content = content, DatePosted = DateTime.Now, Indent = 0, ImageSource = null, LastEdited = DateTime.Now, ReplyId = adId, }; //Find a user and attach him to the DB context var authorFull = db.Users.Attach( db.Users.FirstOrDefault(u => u.Email == authorEmail)); //Attach the user to the Ad comment.Author = authorFull; db.Comments.Add(comment); db.SaveChanges(); return(comment); }
public void DeleteReplies(string replyId) { var db = DbContextControl.GetNew(); var comments = db.Comments.Where(c => c.ReplyId == replyId); db.Comments.RemoveRange(comments); db.SaveChanges(); }
public void BuyBoosts(string email) { var db = DbContextControl.GetNew(); User user = db.Users.FirstOrDefault(u => u.Email == email); user = db.Users.Attach(user); db.Entry(user).Property("Boosts").IsModified = true; user.Boosts += 5; db.SaveChanges(); }
/// <summary> /// A VERY expensive operation that searches through ad content. Use with caution. /// </summary> /// <param name="skip">Skip amount of ads (for paging)</param> /// <param name="amount">Take amount of ads (for paging)</param> /// <param name="location">General location of ad</param> /// <param name="searchQuery">A search query, like a few words that describe what is searched</param> /// <returns>A page of ads that match the criteria.</returns> public IList <Ad> FindAds(int skip, int amount, string location, string searchQuery, AdType type = AdType.All) { //Throttle amount of ads found, to reduce load if (amount > Throttle) { amount = Throttle; } //Get a DB context var db = DbContextControl.GetNew(); //Get all locations that the ad is within IList <string> possibleLocations; try { possibleLocations = GetPossibleLocationNames(location); } catch (LocationNotFoundException) { possibleLocations = new List <string>(); } //Get the keywords for searching in ad content var keywords = searchQuery.GetKeywords(); //Delimit to ads that are within a location, use this as base for the search query //Also order by date posted IQueryable <Ad> query = db.Ads.Include(a => a.Location); //A complex and heavy SQL query to find the searchQuery string within ad titles, contents and categories //We are using the keywords list instead of the searchQuery directly query = (from ad in query where (type == AdType.All || ad.Type == type) && //Check type, all or one (possibleLocations.Count == 0 || //Check location, ignore if none apply possibleLocations.Any(loc => ad.Location.Name == loc)) && (keywords.Count == 0 || //Check for keywords, ignore if none apply keywords.Any(kw => ad.Title.ToLower().Contains(kw) || ad.Content.ToLower().Contains(kw))) ///TODO: Add category search //|| ad.Categories.Contains(kw))) select ad); //Order the query by list //Delimit the query to take only a page of results and append the Authors to the ads var pagedQuery = query.OrderByDescending(a => a.DatePosted) .Skip(skip) .Take(amount) .Include(a => a.Author) .Include(a => a.ReservedBy) .Include(a => a.Price) .ToList(); return(pagedQuery); }
/// <summary> /// Find a location from its name and delete it. /// </summary> public void DeleteLocation(string name) { var db = DbContextControl.GetNew(); var toDelete = new Location { Name = name }; db.Locations.Attach(toDelete); db.Locations.Remove(toDelete); db.SaveChanges(); }
/// <summary> /// Gets all ads reserved by a specific user /// </summary> /// <param name="userEmail"></param> /// <returns></returns> /// <exception cref="UserNotFoundException"></exception> public IList <Ad> GetReservedAds(string userEmail) { User user = UserControl.GetInstance().GetUser(userEmail); var userId = user.Id; var db = DbContextControl.GetNew(); return(db.Ads.Where(a => a.ReservedBy.Id == userId) .Include("Author") .Include("Location") .Include("Price") .Include("ReservedBy") .OrderByDescending(a => a.DatePosted) .ToList()); }
/// <summary> /// Reserves an ad /// </summary> /// <param name="id">Id of ad</param> /// <param name="userEmail">Email of the reserving user</param> /// <exception cref="PostNotFoundException"></exception> /// <exception cref="UserNotFoundException"></exception> /// <exception cref="ArgumentException">Users can not reserve their own Ad.</exception> /// <exception cref="AlreadyReservedException"></exception> /// <exception cref="NotEnoughReservationsException"></exception> public void ReserveAd(string id, string userEmail) { Ad ad = GetAd(id); User user = UserControl.GetInstance().GetUser(userEmail); var db = DbContextControl.GetNew(); using (var reserveTransaction = db.Database.BeginTransaction(System.Data.IsolationLevel.Serializable)) { try { if (user.Id == ad.ReservedBy?.Id) { throw new ArgumentException("Users can not reserve their own ads."); } if (ad.ReservedBy != null) { throw new AlreadyReservedException(String.Format( "Ad with id '{0}' is already reserved by user with id '{1}'", ad.Id, ad.ReservedBy.Id)); } if (user.Reservations < 1) { throw new NotEnoughReservationsException("This user can not reserve any more ads."); } //Get ad into context db.Ads.Attach(ad); db.Entry(ad).State = EntityState.Modified; //Get user into context db.Users.Attach(user); db.Entry(user).State = EntityState.Modified; //Modify ad, reserve ad.ReservedBy = user; //Modify user, remove points user.Reservations -= 1; db.SaveChanges(); reserveTransaction.Commit(); } catch (Exception ex) { reserveTransaction.Rollback(); throw ex; } } }
public void DeleteComment(string id, string userEmail) { var db = DbContextControl.GetNew(); Comment toDelete = db.Comments.Attach( db.Comments.FirstOrDefault(c => c.Id == id)); if (toDelete.Author.Email != userEmail) { throw new InvalidOperationException("Can not delete another person's comment."); } db.Entry(toDelete).State = EntityState.Deleted; db.SaveChanges(); }
public void DeleteUser(string id) { if (id == null) { return; } var db = DbContextControl.GetNew(); User toDelete = new User { Id = id }; db.Entry(toDelete).State = EntityState.Deleted; db.SaveChanges(); }
/// <summary> /// Returns an ordered-by-date list of all comments that are replies to a given post. /// It is not within this method's responsibility to check if the post exists. /// </summary> /// <param name="replyId">The id of the specified post</param> /// <param name="skip">How many comments to skip from the list</param> /// <param name="amount">How many comments to fetch.</param> /// <returns></returns> public IList <Comment> GetReplies(string replyId, int skip, int amount) { if (amount > 64) { amount = 64; //throttling the amount to spare the db server } var db = DbContextControl.GetNew(); IQueryable <Comment> query = db.Comments; var pagedQuery = query.Where(c => c.ReplyId == replyId) .OrderByDescending(c => c.DatePosted) .Skip(skip) .Take(amount) .Include(c => c.Author) .ToList(); return(pagedQuery); }
/// <summary> /// Updates an ad. Requires author email. /// </summary> /// <param name="authorEmail"></param> /// <param name="id"></param> /// <param name="title"></param> /// <param name="content"></param> /// <param name="locationName"></param> /// <param name="type"></param> /// <returns></returns> public Ad UpdateAd(string authorEmail, string id, string title, string content, string locationName = null, AdType type = AdType.Other) { using (var db = DbContextControl.GetNew()) { Ad ad = db.Ads.FirstOrDefault(a => a.Id == id); var entry = db.Entry(ad); if (ad.Author.Email != authorEmail) { throw new InvalidOperationException("Can not edit another person's ad!"); } if (title != null && title != ad.Title) { ad.Title = title; entry.Property("Title").IsModified = true; } //Find a location and attach it to the DB context and to the Ad if (locationName != null && locationName != ad.Location.Name) { var locationFull = db.Locations.Attach(new Location { Name = locationName }); //ad.Location = locationFull; entry.Reference("Location").CurrentValue = locationFull; } if (content != null && content != ad.Content) { ad.Content = content; entry.Property("Content").IsModified = true; } ad.LastEdited = DateTime.Now; entry.Property("LastEdited").IsModified = true; db.SaveChanges(); return(ad); } }
/// <summary> /// Posts an Ad, persists to the database /// </summary> /// <param name="authorEmail"></param> /// <param name="title"></param> /// <param name="content"></param> /// <param name="locationName"></param> /// <param name="type"></param> /// <returns></returns> public Ad PostAd(string authorEmail, string title, string content, string locationName = null, AdType type = AdType.Other) { var db = DbContextControl.GetNew(); Ad ad = new Ad { Content = content, DatePosted = DateTime.Now, LastEdited = DateTime.Now, ExpDate = DateTime.Now, Views = 0, Title = title, Location = null, Price = null, Type = type, }; //Find a user and attach him to the DB context var authorFull = db.Users.Attach( db.Users.FirstOrDefault(u => u.Email == authorEmail)); //Attach the user to the Ad ad.Author = authorFull; //Find a location and attach it to the DB context and to the Ad if (locationName != null) { var locationFull = db.Locations.Attach(new Location { Name = locationName }); ad.Location = locationFull; } ad.Price = new Price { Id = ad.Id, Type = PriceType.Free, High = 0, Low = 0 }; db.Ads.Add(ad); db.SaveChanges(); return(ad); }
/// <summary> /// This is an administrative method, not available to users. /// </summary> public void RegisterLocation(string name, LocationType type, string parentName = null) { var db = DbContextControl.GetNew(); Location parent = null; if (parentName != null) { parent = AttachLocation(db, parentName); } Location location = new Location { Name = name, Type = type, Parent = parent, }; db.Locations.Add(location); db.SaveChanges(); }
/// <summary> /// Fetches from all ads. Ordered by date. This method is used on the home page. /// </summary> public IList <Ad> GetAds(int skip, int amount) { if (amount > Throttle) { amount = Throttle; } var db = DbContextControl.GetNew(); IQueryable <Ad> query = db.Ads; var pagedQuery = query .OrderByDescending(a => a.DatePosted) .Skip(skip) .Take(amount) .Include(a => a.Author) .Include(a => a.Location) .Include(a => a.ReservedBy) .ToList(); return(pagedQuery); }
private void SeedAds() { //TODO: Refactor var db = DbContextControl.GetNew(); if (db.Ads.Count() == 0) { if (db.Users.Count() == 0) { MigrationSeed.SeedUsers(); } MigrationSeed.SeedAds(); foreach (var ad in MigrationSeed.Ads) { PostAd(ad.Author.Email, ad.Title, ad.Content, ad.Location.Name, ad.Type); } var blueCar = MigrationSeed.Ads.FirstOrDefault(a => a.Title == "Selling blue sports car"); ReserveAd(blueCar?.Id, "*****@*****.**"); CommentControl.GetInstance().PostComment(blueCar.Id, "Interested!", "*****@*****.**"); } }