Click here to Skip to main content
15,897,291 members
Articles / Desktop Programming / Windows Forms

Code First: A Practical Case

Rate me:
Please Sign up or sign in to vote.
4.89/5 (19 votes)
26 Feb 2012CPOL15 min read 72.4K   3.7K   67  
A code first real life data model case
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data.Entity;
using Xah.MediaCatalogerLib.Model;
using Xah.MediaCatalogerLib.Model.Files;
using Xah.MediaCatalogerLib.Model.Meta;

namespace Xah.MediaCatalogerLib.TreeProcess
{
    interface ICancelable
    {
        bool IsCancelled { get; }
        void Cancel();
    }

    abstract class ATreeVisitor : ITreeVisitor, ICancelable
    {
        #region ITreeVisitor implementation
        public abstract void Visit(TreeFileItem fileItem);
        public abstract void Visit(TreeFolderItem folderItem);
        #endregion

        #region ICancelable Members
        protected bool cancelled = false;

        public bool IsCancelled
        {
            get { return cancelled; }
        }

        public void Cancel()
        {
            cancelled = true;
        }
        #endregion
    }

    class PopulateTreeVisitor : ATreeVisitor
    {
        private string[] extensions = new string[0];

        #region ATreeVisitor implementation
        public override void Visit(TreeFileItem fileItem)
        {
            // do nothing
        }

        public override void Visit(TreeFolderItem folderItem)
        {
            string path = folderItem.Path;
            if (!Directory.Exists(path)) return;

            // populate children folders
            string[] folders = Directory.GetDirectories(path);
            foreach (string folder in folders)
            {
                if (IsCancelled) return;

                DirectoryInfo di = new DirectoryInfo(folder);
                TreeFolderItem tfi = new TreeFolderItem(di.Name);
                folderItem.AddItem(tfi);
                tfi.Accept(this);
            }

            // populate children files
            List<string> files = new List<string>();
            foreach (string extension in extensions)
            {
                if (IsCancelled) return;

                string mask = String.Format("*.{0}", extension.Trim('.', ' '));
                files.AddRange(Directory.GetFiles(path, mask));
            }

            files.ForEach(x => folderItem.AddItem(new TreeFileItem(Path.GetFileName(x))));
        }
        #endregion

        public PopulateTreeVisitor(string[] extensions)
        {
            this.extensions = extensions;
        }
    }

    class FileListerTreeVisitor : ATreeVisitor
    {
        public List<TreeFileItem> Files { get; private set; }

        #region ATreeVisitor implementation
        public override void Visit(TreeFileItem fileItem)
        {
            if (IsCancelled) return;

            Files.Add(fileItem);
        }

        public override void Visit(TreeFolderItem folderItem)
        {
            if (IsCancelled) return;

            folderItem.Children.ForEach(x => x.Accept(this));
        }
        #endregion

        public FileListerTreeVisitor()
        {
            Files = new List<TreeFileItem>();
        }
    }

    abstract class AFileProcessorTreeVisitor : ATreeVisitor
    {
        public delegate void OnFileProcessedCb(TreeFileItem fileItem);
        public event OnFileProcessedCb OnFileProcessed;

        protected readonly MediaCatalog db;
        protected readonly MediaFolder folder;

        #region Abstract methods
        protected abstract void PreprocessFolder(TreeFolderItem folderItem);
        protected abstract void PostprocessFolder(TreeFolderItem folderItem);
        #endregion

        #region ATreeVisitor implementation
        public override void Visit(TreeFileItem fileItem)
        {
            if (IsCancelled) return;

            try
            {
                if (!db.ExistsMediaFile(folder.MediaType, fileItem.Path))
                    fileItem.Tag = MediaFile.Create(db, folder, fileItem.Path);

                if (OnFileProcessed != null)
                    OnFileProcessed(fileItem);
            }
            catch { }
        }

        public override void Visit(TreeFolderItem folderItem)
        {
            if (IsCancelled) return;

            PreprocessFolder(folderItem);
            folderItem.Children.ForEach(x => x.Accept(this));
            PostprocessFolder(folderItem);

            // Get file list
            List<MediaFile> files = folderItem.Children.Select(x => x.Tag).OfType<MediaFile>().ToList();
            if (files.Count == 0) return;

            try
            {
                // Add files to database and save changes
                files.ForEach(x => x.Add(db));
                db.SaveChanges();
            }
            catch (System.Data.Entity.Validation.DbEntityValidationException ex)
            {
                // Trace error
                System.Diagnostics.Trace.TraceError("--------------------------------------------");
                foreach (System.Data.Entity.Validation.DbEntityValidationResult errs in ex.EntityValidationErrors)
                {
                    foreach (System.Data.Entity.Validation.DbValidationError err in errs.ValidationErrors)
                        System.Diagnostics.Trace.TraceError("ERROR - {0}|{1}: {2}", err.PropertyName, ((object)errs.Entry).GetType().ToString(), err.ErrorMessage);
                }
                System.Diagnostics.Trace.TraceError("--------------------------------------------");
            }
            catch (System.Data.Entity.Infrastructure.DbUpdateException ex)
            {
                // Trace error
                System.Diagnostics.Trace.TraceError("--------------------------------------------");
                foreach (var st in ex.Entries)
                {
                    System.Diagnostics.Trace.TraceError("ERROR - {0}|{1}: {2}", st.State.ToString(), ((object)st.Entity).GetType().ToString(), ex.Message);
                }
            }
        }
        #endregion

        protected AFileProcessorTreeVisitor(MediaCatalog db, MediaFolder folder)
        {
            this.db = db;
            this.folder = folder;
        }

        public static AFileProcessorTreeVisitor Create(MediaCatalog db, MediaFolder folder)
        {
            AFileProcessorTreeVisitor processor = null;

            switch (folder.MediaType)
            {
                case MediaFileType.Video:
                    processor = new VideoFileProcessorTreeVisitor(db, folder);
                    break;

                case MediaFileType.Audio:
                    processor = new AudioFileProcessorTreeVisitor(db, folder);
                    break;
            }

            return processor;
        }
    }

    class VideoFileProcessorTreeVisitor : AFileProcessorTreeVisitor
    {
        #region AFileProcessorTreeVisitor implementation
        protected override void PreprocessFolder(TreeFolderItem folderItem)
        {
            // do nothing
        }

        protected override void PostprocessFolder(TreeFolderItem folderItem)
        {
            // do nothing
        }
        #endregion

        public VideoFileProcessorTreeVisitor(MediaCatalog db, MediaFolder folder) : base(db, folder) { }
    }

    class AudioFileProcessorTreeVisitor : AFileProcessorTreeVisitor
    {
        #region AFileProcessorTreeVisitor implementation
        protected override void PreprocessFolder(TreeFolderItem folderItem)
        {
            // do nothing
        }

        protected override void PostprocessFolder(TreeFolderItem folderItem)
        {
            // Get folder audio files
            var trackFiles = folderItem.Children.Select(x => x.Tag).OfType<AudioFile>().ToList();
            if (trackFiles.Count == 0) return;

            // Select list with AudioFileMetaInfo
            var trackInfos = trackFiles.Select(x => x.AlbumTrackInfo).Where(x => x != null).ToList();

            // Create AudioAlbumMetalnfo
            AudioAlbumMetalnfo albumInfo = new AudioAlbumMetalnfo(db, trackInfos);
            AudioAlbumMetalnfo existingAlbumInfo = db.Albums.FirstOrDefault(x => x.Artist.Equals(albumInfo.Artist) && x.Album.Equals(albumInfo.Album));
            if (existingAlbumInfo != null) albumInfo = existingAlbumInfo;

            // Associate album info with audio files
            trackFiles.ForEach(x => x.AlbumInfo = albumInfo);
        }
        #endregion

        public AudioFileProcessorTreeVisitor(MediaCatalog db, MediaFolder folder) : base(db, folder) { }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Spain Spain
I studied Telecommunication with spezialization in Sound & Image. I was always very interested in programming at university as well and that is how I earn a living.

Since some years ago, I am also succesfully involved in software architecture and design.

Comments and Discussions