/// <summary>
        /// Insert all metadata items from the data store for the specified media object. Assumes no existing metadata record exists
        /// that matches the MediaObjectMetadataId value of each metadata item. Each metadata item is inserted and the newly
        /// assigned MediaObjectMetadataId value is assigned to the item's MediaObjectMetadataId property.
        /// </summary>
        /// <param name="mediaObject">The media object for which to insert all metadata items to the data store.</param>
        /// <param name="ctx">A database context.</param>
        private static void InsertMetadataItems(IGalleryObject mediaObject, GspContext ctx)
        {
            // Insert meta data items, if any, into MediaObjectMetadata table.
            if (mediaObject.MetadataItems.Count > 0)
            {
                foreach (IGalleryObjectMetadataItem metaDataItem in mediaObject.MetadataItems)
                {
                    MediaObjectMetadataDto mDto = new MediaObjectMetadataDto
                                                                                    {
                                                                                        FKMediaObjectId = mediaObject.Id,
                                                                                        MetadataNameIdentifier = (int)metaDataItem.MetadataItemName,
                                                                                        Description = metaDataItem.Description,
                                                                                        Value = metaDataItem.Value
                                                                                    };

                    ctx.MediaObjectMetadatas.Add(mDto);
                    // Note: The newly assigned ID is not assigned back to metaDataItem.MediaObjectMetadataId, but that should be
                    // OK because we'll be reloading the items from the DB after the save.
                }
            }
        }
        /// <summary>
        /// Persist each each metadata item that has HasChanges = true to the data store. If all items are marked for updating
        /// (mediaObject.RegenerateMetadataOnSave = true), then all metadata items are deleted from the data store and then inserted based
        /// on the current metadata items. If one or more items has HasChanges = false, then each item with HasChanges = true is
        /// processed according to the following rules: (1) If the metadata value is null or an empty string, it is deleted from the
        /// data store and removed from the MetadataItems collection. (2) If the item's MediaObjectMetadataId = int.MinValue, the
        /// item is assumed to be new and is inserted. (3) Any item not falling into the previous two categories, but HasChanges = true,
        /// is assumed to be pre-existing and an update stored procedure is executed.
        /// </summary>
        /// <param name="mediaObject">The media object for which to update metadata items in the data store.</param>
        /// <param name="ctx">A database context.</param>
        private static void UpdateMetadataItems(IGalleryObject mediaObject, GspContext ctx)
        {
            if (mediaObject.ExtractMetadataOnSave)
            {
                // User wants to replace all metadata items. Delete them all from the data store, then insert the ones we have.
                DeleteMetadataItems(mediaObject, ctx);

                InsertMetadataItems(mediaObject, ctx);
            }
            else
            {
                IGalleryObjectMetadataItemCollection metadataItemsToSave = mediaObject.MetadataItems.GetItemsToSave();
                if (metadataItemsToSave.Count == 0)
                {
                    return; // Nothing to save
                }

                // There is at least one item to persist to the data store.
                foreach (IGalleryObjectMetadataItem metaDataItem in metadataItemsToSave)
                {
                    if (String.IsNullOrEmpty(metaDataItem.Value))
                    {
                        // There is no value, so let's delete this item.
                        DeleteMetadataItem(metaDataItem, ctx);

                        // Remove it from the collection.
                        mediaObject.MetadataItems.Remove(metaDataItem);
                    }
                    else if (metaDataItem.MediaObjectMetadataId == int.MinValue)
                    {
                        // Insert the item.
                        MediaObjectMetadataDto mDto = new MediaObjectMetadataDto
                                                                                        {
                                                                                            FKMediaObjectId = mediaObject.Id,
                                                                                            MetadataNameIdentifier = (int)metaDataItem.MetadataItemName,
                                                                                            Description = metaDataItem.Description,
                                                                                            Value = metaDataItem.Value
                                                                                        };

                        ctx.MediaObjectMetadatas.Add(mDto);
                        // Note: The newly assigned ID is not assigned back to metaDataItem.MediaObjectMetadataId, but that should be
                        // OK because we'll be reloading the items from the DB after the save.
                    }
                    else
                    {
                        // Update the item.
                        MediaObjectMetadataDto mDto = ctx.MediaObjectMetadatas.Find(metaDataItem.MediaObjectMetadataId);

                        if (mDto != null)
                        {
                            mDto.MetadataNameIdentifier = (int)metaDataItem.MetadataItemName;
                            mDto.Description = metaDataItem.Description;
                            mDto.Value = metaDataItem.Value;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Insert all metadata items from the data store for the specified media object. Assumes no existing metadata record exists
        /// that matches the MediaObjectMetadataId value of each metadata item. Each metadata item is inserted and the newly
        /// assigned MediaObjectMetadataId value is assigned to the item's MediaObjectMetadataId property.
        /// </summary>
        /// <param name="mediaObject">The media object for which to insert all metadata items to the data store.</param>
        /// <param name="ctx">A database context.</param>
        private static void InsertMetadataItems(IGalleryObject mediaObject, GspContext ctx)
        {
            // Insert meta data items, if any, into MediaObjectMetadata table.
            if (mediaObject.MetadataItems.Count > 0)
            {
                int tmpId = 0;
                var mDtos = new Dictionary<int, MediaObjectMetadataDto>();
                var metas = new Dictionary<int, IGalleryObjectMetadataItem>();

                foreach (IGalleryObjectMetadataItem metaDataItem in mediaObject.MetadataItems)
                {
                    MediaObjectMetadataDto mDto = new MediaObjectMetadataDto
                                    {
                                        FKMediaObjectId = mediaObject.Id,
                                        MetadataNameIdentifier = (int)metaDataItem.MetadataItemName,
                                        Description = metaDataItem.Description,
                                        Value = metaDataItem.Value
                                    };

                    ctx.MediaObjectMetadatas.Add(mDto);

                    metas.Add(++tmpId, metaDataItem);
                    mDtos.Add(tmpId, mDto);
                }

                ctx.SaveChanges();

                // Loop through each metadata item again, find the matching DTO object, and update
                // the newly assigned ID.
                foreach (KeyValuePair<int, IGalleryObjectMetadataItem> kvp in metas)
                {
                    MediaObjectMetadataDto mDto;
                    if (mDtos.TryGetValue(kvp.Key, out mDto))
                    {
                        kvp.Value.MediaObjectMetadataId = mDto.MediaObjectMetadataId;
                    }
                }
            }
        }