protected override PresetMetadata createFunc(PresetMetadata preset)
        {
            if (String.IsNullOrEmpty(preset.Name) || String.IsNullOrWhiteSpace(preset.Name))
            {
                throw new DbEntityValidationException("Error updating presetMetadata, name cannot be null, empty or whitespace");
            }

            PresetMetadata newPreset = new PresetMetadata();

            Db.PresetMetadatas.Add(newPreset);
            Db.Entry <PresetMetadata>(newPreset).CurrentValues.SetValues(preset);
            newPreset.Id = 0;

            TagDbCommands tagCommands = new TagDbCommands(Db);

            foreach (Tag tag in preset.Tags)
            {
                Tag addTag = tagCommands.getTagById(tag.Id);

                if (addTag != null)
                {
                    newPreset.Tags.Add(addTag);
                }
            }

            Db.SaveChanges();

            return(newPreset);
        }
        protected override PresetMetadata updateFunc(PresetMetadata updatePreset)
        {
            if (String.IsNullOrEmpty(updatePreset.Name) || String.IsNullOrWhiteSpace(updatePreset.Name))
            {
                throw new DbEntityValidationException("Error updating presetMetadata, name cannot be null, empty or whitespace");
            }

            PresetMetadata preset = getPresetMetadataById(updatePreset.Id);

            if (preset == null)
            {
                throw new DbEntityValidationException("Cannot update non-existing tag id: " + updatePreset.Id.ToString());
            }
            Db.Entry <PresetMetadata>(preset).CurrentValues.SetValues(updatePreset);

            preset.Tags.Clear();

            TagDbCommands tagCommands = new TagDbCommands(Db);

            foreach (Tag updateTag in updatePreset.Tags)
            {
                Tag tag = tagCommands.getTagById(updateTag.Id);

                if (tag == null)
                {
                    Logger.Log.Warn("Cannot add non-existent tag: " + updateTag.Id.ToString() + " to presetMetadata: " + preset.Id.ToString());
                    continue;
                }

                preset.Tags.Add(tag);
            }

            Db.SaveChanges();

            return(preset);
        }
        protected override BaseMetadata updateFunc(BaseMetadata metadata)
        {
            if (String.IsNullOrEmpty(metadata.Location) || String.IsNullOrWhiteSpace(metadata.Location))
            {
                throw new DbEntityValidationException("Error updating metadata, location cannot be null, empty or whitespace");
            }

            BaseMetadata updateMetadata = Db.BaseMetadatas.FirstOrDefault(t => t.Id == metadata.Id);

            if (updateMetadata == null)
            {
                throw new DbEntityValidationException("Cannot update non existing metadata: " + metadata.Id.ToString());
            }

            if (metadata is VideoMetadata)
            {
                Db.Entry <VideoMetadata>(updateMetadata as VideoMetadata).CurrentValues.SetValues(metadata);
            }
            else if (metadata is ImageMetadata)
            {
                Db.Entry <ImageMetadata>(updateMetadata as ImageMetadata).CurrentValues.SetValues(metadata);
            }
            else if (metadata is AudioMetadata)
            {
                Db.Entry <AudioMetadata>(updateMetadata as AudioMetadata).CurrentValues.SetValues(metadata);
            }

            //updateMetadata.calcHashes();

            FileInfo info = new FileInfo(updateMetadata.Location);

            info.Refresh();
            updateMetadata.LastModifiedDate = info.LastWriteTime;

            if (updateMetadata.Thumbnail != null)
            {
                if ((metadata.Thumbnail != null && updateMetadata.Thumbnail.Id != metadata.Thumbnail.Id) ||
                    metadata.Thumbnail == null)
                {
                    Db.Thumbnails.Remove(updateMetadata.Thumbnail);
                }
            }

            if (metadata.Thumbnail != null)
            {
                if (metadata.Thumbnail.Id != 0)
                {
                    //thumbnail already exists
                    Thumbnail existing = Db.Thumbnails.FirstOrDefault(t => t.Id == metadata.Thumbnail.Id);
                    updateMetadata.Thumbnail = existing;
                }
                else
                {
                    Db.Thumbnails.Add(metadata.Thumbnail);
                    updateMetadata.Thumbnail = metadata.Thumbnail;
                }
            }


            TagDbCommands tagCommands = new TagDbCommands(Db);

            // remove tags
            for (int i = updateMetadata.Tags.Count - 1; i >= 0; i--)
            {
                Tag tag = updateMetadata.Tags.ElementAt(i);

                if (!metadata.Tags.Contains(tag, EqualityComparer <Tag> .Default))
                {
                    updateMetadata.Tags.Remove(tag);
                    tag.Used -= 1;
                }
            }

            // add tags
            foreach (Tag tag in metadata.Tags)
            {
                Tag result = tagCommands.getTagByName(tag.Name);

                if (result == null)
                {
                    result = tagCommands.create(tag);
                }

                if (!updateMetadata.Tags.Contains(result, EqualityComparer <Tag> .Default))
                {
                    updateMetadata.Tags.Add(result);
                    result.Used += 1;
                }
            }

            Db.SaveChanges();

            updateMetadata.IsImported = true;

            return(updateMetadata);
        }
        protected override BaseMetadata createFunc(BaseMetadata metadata)
        {
            if (String.IsNullOrEmpty(metadata.Location) || String.IsNullOrWhiteSpace(metadata.Location))
            {
                throw new DbEntityValidationException("Error creating metadata, location cannot be null, empty or whitespace");
            }

            if (Db.BaseMetadatas.Any(t => t.Location == metadata.Location && t.Name == metadata.Name))
            {
                throw new DbEntityValidationException("Cannot create metadata with duplicate location: " + metadata.Location);
            }

            BaseMetadata newMetadata = null;

            if (metadata is VideoMetadata)
            {
                VideoMetadata videoMetadata = new VideoMetadata(metadata.Location, null);
                Db.BaseMetadatas.Add(videoMetadata);

                Db.Entry <VideoMetadata>(videoMetadata).CurrentValues.SetValues(metadata);
                newMetadata = videoMetadata;
            }
            else if (metadata is ImageMetadata)
            {
                ImageMetadata imageMetadata = new ImageMetadata(metadata.Location, null);
                Db.BaseMetadatas.Add(imageMetadata);

                Db.Entry <ImageMetadata>(imageMetadata).CurrentValues.SetValues(metadata);
                newMetadata = imageMetadata;
            }
            else if (metadata is AudioMetadata)
            {
                AudioMetadata audioMetadata = new AudioMetadata(metadata.Location, null);
                Db.BaseMetadatas.Add(audioMetadata);

                Db.Entry <AudioMetadata>(audioMetadata).CurrentValues.SetValues(metadata);
                newMetadata = audioMetadata;
            }

            //newMetadata.calcHashes();

            FileInfo info = new FileInfo(newMetadata.Location);

            info.Refresh();

            if (info.LastWriteTime < (DateTime)SqlDateTime.MinValue)
            {
                Logger.Log.Warn("LastWriteTime for " + newMetadata.Location + " smaller as SqlDateTime.MinValue");
                newMetadata.LastModifiedDate = (DateTime)SqlDateTime.MinValue;
            }
            else
            {
                newMetadata.LastModifiedDate = info.LastWriteTime;
            }

            newMetadata.Id = 0;

            if (metadata.Thumbnail != null)
            {
                if (metadata.Thumbnail.Id != 0)
                {
                    //thumbnail already exists
                    Thumbnail existing = Db.Thumbnails.FirstOrDefault(t => t.Id == metadata.Thumbnail.Id);
                    newMetadata.Thumbnail = existing;
                }
                else
                {
                    Db.Thumbnails.Add(metadata.Thumbnail);
                    newMetadata.Thumbnail = metadata.Thumbnail;
                }
            }

            TagDbCommands tagCommands = new TagDbCommands(Db);

            foreach (Tag tag in metadata.Tags)
            {
                Tag result = tagCommands.getTagByName(tag.Name);

                if (result == null)
                {
                    result = tagCommands.create(tag);
                }

                result.Used += 1;
                newMetadata.Tags.Add(result);
            }

            int maxRetries = 15;

            do
            {
                try
                {
                    Db.SaveChanges();
                    maxRetries = 0;
                }
                catch (DbUpdateConcurrencyException e)
                {
                    if (--maxRetries == 0)
                    {
                        throw;
                    }

                    foreach (DbEntityEntry conflictingEntity in e.Entries)
                    {
                        if (conflictingEntity.Entity is Tag)
                        {
                            // reload the conflicting tag (database wins)
                            conflictingEntity.Reload();
                            (conflictingEntity.Entity as Tag).Used += 1;
                        }
                        else
                        {
                            throw;
                        }
                    }

                    Random random = new Random();

                    Thread.Sleep(random.Next(50, 100));
                }
            } while (maxRetries > 0);

            newMetadata.IsImported = true;

            return(newMetadata);
        }