public void RemoveTags(string photoId, Tag[] tags) { var context = new PhotoAlbumDataContext(); foreach (var tag in tags) { var photoTag = new PhotoTagRow(photoId, tag.Name); context.AttachTo(PhotoAlbumDataContext.PhotoTagTable, photoTag, "*"); context.DeleteObject(photoTag); } try { // continue trying to delete, even if not found context.SaveChanges(SaveChangesOptions.ContinueOnError); } catch (DataServiceRequestException ex) { foreach (var resp in ex.Response) { // to be more robust, we will ignore 404 errors when // the entity might have already been deleted (due to an // incomplete operation earliet). if (resp.StatusCode != (int)HttpStatusCode.NotFound && resp.StatusCode != (int)HttpStatusCode.OK) { throw; } } } }
public void CreateTags(string photoId, Tag[] tags) { var context = new PhotoAlbumDataContext(); foreach (var tag in tags) { // add the tag and associate to a picture for later searching context.AddObject(PhotoAlbumDataContext.TagTable, new TagRow(tag)); context.AddObject(PhotoAlbumDataContext.PhotoTagTable, new PhotoTagRow(photoId, tag.Name)); } try { // we want to continue - even if conflict is detected... context.SaveChanges(SaveChangesOptions.ContinueOnError); } catch (DataServiceRequestException ex) { foreach (var resp in ex.Response) { // we might get a conflict here, which is ok (tag exists) // the alternative is to query everytime to see if the tag // exists, which is less efficient that just trying and // handling exception. if (resp.StatusCode != (int)HttpStatusCode.Conflict && resp.StatusCode != (int)HttpStatusCode.Created) { throw; } } } }
public void UpdateAlbumData(string owner, string albumId, string thumbnailUrl) { var context = new PhotoAlbumDataContext(); var albumRow = new AlbumRow(new Album() { AlbumId = albumId, Owner = owner }); var album = context.Albums.Where(a => a.PartitionKey == albumRow.PartitionKey && a.RowKey == albumRow.RowKey && a.ThumbnailUrl == thumbnailUrl) .AsTableServiceQuery() .FirstOrDefault(); if (album != null) { // get the first the photo in the album to update the thumbnail var photoRow = new PhotoRow(new Photo { Owner = owner.ToLowerInvariant(), AlbumId = albumId }); var otherPhoto = context.Photos.Where(p => p.PartitionKey == photoRow.PartitionKey).Take(1).SingleOrDefault(); // if the album is empty, we set the HasPhotos property to false to hide it from the UI if (otherPhoto != null) { album.ThumbnailUrl = otherPhoto.ThumbnailUrl; } else { album.ThumbnailUrl = string.Empty; album.HasPhotos = false; } this.UpdateAlbum(album.ToModel()); } }
public IEnumerable <Album> GetAlbums() { var context = new PhotoAlbumDataContext(); return(context.Albums.AsTableServiceQuery() .AsEnumerable() .ToModel()); }
public IEnumerable <Photo> FindPhotosByTag(params string[] tags) { var context = new PhotoAlbumDataContext(); // we have to dynamically build our query using an Expression tree Expression <Func <PhotoTagRow, bool> > search = null; foreach (var tag in tags) { var id = tag.Trim().ToLowerInvariant(); if (string.IsNullOrEmpty(id)) { continue; } Expression <Func <PhotoTagRow, bool> > addendum = t => t.PartitionKey == id; if (search == null) { search = addendum; } else { search = Expression.Lambda <Func <PhotoTagRow, bool> >(Expression.OrElse(search.Body, addendum.Body), search.Parameters); } } // if we get back entries associated with the tag, we next have to query // to find the specific picture. if (search != null) { var rows = context.PhotoTags.Where(search).AsTableServiceQuery(); Expression <Func <PhotoRow, bool> > photoPredicate = null; foreach (var row in rows) { var id = row.PhotoId; Expression <Func <PhotoRow, bool> > addendum = p => p.RowKey == id; if (photoPredicate == null) { photoPredicate = addendum; } else { photoPredicate = Expression.Lambda <Func <PhotoRow, bool> >(Expression.OrElse(photoPredicate.Body, addendum.Body), photoPredicate.Parameters); } } if (photoPredicate != null) { return(context.Photos.Where(photoPredicate).AsTableServiceQuery().ToModel()); } } // by default, return an empty (non-null) enumeration return((new Photo[] { }).AsEnumerable()); }
public IEnumerable <Album> GetAlbumsByOwner(string owner) { var context = new PhotoAlbumDataContext(); return(context.Albums.Where(a => a.PartitionKey == owner).AsTableServiceQuery() .AsEnumerable() .ToModel()); // TODO: Implement paging }
public void UpdatePhotoData(Photo photo) { var context = new PhotoAlbumDataContext(); var photoRow = new PhotoRow(photo); // attach and update the photo row context.AttachTo(PhotoAlbumDataContext.PhotoTable, photoRow, "*"); context.UpdateObject(photoRow); context.SaveChanges(); }
public void UpdateAlbum(Album album) { var context = new PhotoAlbumDataContext(); var albumRow = new AlbumRow(album); // attach and update the photo row context.AttachTo(PhotoAlbumDataContext.AlbumTable, albumRow, "*"); context.UpdateObject(albumRow); context.SaveChanges(); }
public IEnumerable<Photo> GetPhotosByAlbum(string owner, string albumId) { var context = new PhotoAlbumDataContext(); // use this partial one to correctly construct partition keys var temp = new PhotoRow(new Photo { Owner = owner.ToLowerInvariant(), AlbumId = albumId }); return context.Photos.Where(p => p.PartitionKey == temp.PartitionKey).AsTableServiceQuery() .AsEnumerable() .ToModel(); // TODO: Handle Paging }
public Photo GetPhotoByOwner(string owner, string albumId, string photoId) { var context = new PhotoAlbumDataContext(); // use this partial one to correctly construct partition keys var temp = new PhotoRow(new Photo { Owner = owner.ToLowerInvariant(), AlbumId = albumId, PhotoId = photoId }); // we add the 'true' predicate in order to not get 404 if photo is missing (we just want a null) return context.Photos.Where(p => p.PartitionKey == temp.PartitionKey && p.RowKey == temp.RowKey && true).AsTableServiceQuery() .AsEnumerable() .ToModel() .SingleOrDefault(); }
public void Delete(Photo photo) { var context = new PhotoAlbumDataContext(); var photoRow = new PhotoRow(photo); context.AttachTo(PhotoAlbumDataContext.PhotoTable, photoRow, "*"); context.DeleteObject(photoRow); context.SaveChanges(); // tell the worker role to clean up blobs and tags this.SendToQueue( Constants.PhotoCleanupQueue, string.Format(CultureInfo.InvariantCulture, "{0}|{1}|{2}|{3}|{4}|{5}", photo.PhotoId, photo.Owner, photo.Url, photo.RawTags, photo.ThumbnailUrl, photo.AlbumId)); }
public void CreateAlbum(string albumName, string owner) { var context = new PhotoAlbumDataContext(); var album = new Album { AlbumId = SlugHelper.GetSlug(albumName), Owner = owner.ToLowerInvariant(), Title = albumName }; context.AddObject(PhotoAlbumDataContext.AlbumTable, new AlbumRow(album)); context.SaveChanges(); }
public Photo GetPhotoByOwner(string owner, string albumId, string photoId) { var context = new PhotoAlbumDataContext(); // use this partial one to correctly construct partition keys var temp = new PhotoRow(new Photo { Owner = owner.ToLowerInvariant(), AlbumId = albumId, PhotoId = photoId }); // we add the 'true' predicate in order to not get 404 if photo is missing (we just want a null) return(context.Photos.Where(p => p.PartitionKey == temp.PartitionKey && p.RowKey == temp.RowKey && true).AsTableServiceQuery() .AsEnumerable() .ToModel() .SingleOrDefault()); }
public IEnumerable <Photo> GetPhotosByAlbum(string owner, string albumId) { var context = new PhotoAlbumDataContext(); // use this partial one to correctly construct partition keys var temp = new PhotoRow(new Photo { Owner = owner.ToLowerInvariant(), AlbumId = albumId }); return(context.Photos.Where(p => p.PartitionKey == temp.PartitionKey).AsTableServiceQuery() .AsEnumerable() .ToModel()); // TODO: Handle Paging }
public void DeleteAlbum(string albumName, string owner) { var context = new PhotoAlbumDataContext(); // find the album by name and owner (we don't pass in ugly GUIDs for direct access var album = context.Albums .Where(a => a.AlbumId == albumName && a.PartitionKey == owner.ToLowerInvariant()).AsTableServiceQuery() .Single(); context.DeleteObject(album); context.SaveChanges(); // tell the worker role to clean up blobs and tags this.SendToQueue( Constants.AlbumCleanupQueue, string.Format(CultureInfo.InvariantCulture, "{0}|{1}", owner, album.AlbumId)); }
public void Delete(string owner, string album, string photoId) { var context = new PhotoAlbumDataContext(); // we use this to help calculate partition keys, rowkeys in query later var temp = new PhotoRow(new Photo { PhotoId = photoId, AlbumId = album, Owner = owner.ToLowerInvariant() }); // see if the photo exists var photo = context.Photos.Where(p => p.PartitionKey == temp.PartitionKey && p.RowKey == temp.RowKey && true).AsTableServiceQuery() .ToModel() .SingleOrDefault(); if (photo != null) { this.Delete(photo); } }
public void Add(Photo photo, Stream binary, string mimeType, string name) { // get just the file name and ignore the path var file = name.Substring(name.LastIndexOf("\\", StringComparison.OrdinalIgnoreCase) + 1); var context = new PhotoAlbumDataContext(); try { // add the photo to table storage context.AddObject(PhotoAlbumDataContext.PhotoTable, new PhotoRow(photo)); context.SaveChanges(); } catch (Exception ex) { if (ex.ToString().Contains("EntityAlreadyExists")) { throw new PhotoNameAlreadyInUseException(photo.AlbumId, photo.Title); } else { throw; } } // add the binary to blob storage var storage = this.storageAccount.CreateCloudBlobClient(); var container = storage.GetContainerReference(photo.Owner.ToLowerInvariant()); container.CreateIfNotExist(); container.SetPermissions(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob }); var blob = container.GetBlobReference(file); blob.Properties.ContentType = mimeType; blob.UploadFromStream(binary); // post a message to the queue so it can process tags and the sizing operations this.SendToQueue( Constants.PhotoQueue, string.Format(CultureInfo.InvariantCulture, "{0}|{1}|{2}|{3}", photo.Owner, photo.AlbumId, photo.PhotoId, file)); }
public IEnumerable<Photo> FindPhotosByTag(params string[] tags) { var context = new PhotoAlbumDataContext(); // we have to dynamically build our query using an Expression tree Expression<Func<PhotoTagRow, bool>> search = null; foreach (var tag in tags) { var id = tag.Trim().ToLowerInvariant(); if (string.IsNullOrEmpty(id)) { continue; } Expression<Func<PhotoTagRow, bool>> addendum = t => t.PartitionKey == id; if (search == null) { search = addendum; } else { search = Expression.Lambda<Func<PhotoTagRow, bool>>(Expression.OrElse(search.Body, addendum.Body), search.Parameters); } } // if we get back entries associated with the tag, we next have to query // to find the specific picture. if (search != null) { var rows = context.PhotoTags.Where(search).AsTableServiceQuery(); Expression<Func<PhotoRow, bool>> photoPredicate = null; foreach (var row in rows) { var id = row.PhotoId; Expression<Func<PhotoRow, bool>> addendum = p => p.RowKey == id; if (photoPredicate == null) { photoPredicate = addendum; } else { photoPredicate = Expression.Lambda<Func<PhotoRow, bool>>(Expression.OrElse(photoPredicate.Body, addendum.Body), photoPredicate.Parameters); } } if (photoPredicate != null) { return context.Photos.Where(photoPredicate).AsTableServiceQuery().ToModel(); } } // by default, return an empty (non-null) enumeration return (new Photo[] { }).AsEnumerable(); }
public IEnumerable<Album> GetAlbumsByOwner(string owner) { var context = new PhotoAlbumDataContext(); return context.Albums.Where(a => a.PartitionKey == owner).AsTableServiceQuery() .AsEnumerable() .ToModel(); // TODO: Implement paging }
public IEnumerable<Album> GetAlbums() { var context = new PhotoAlbumDataContext(); return context.Albums.AsTableServiceQuery() .AsEnumerable() .ToModel(); }