Click here to Skip to main content
15,891,864 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.2K   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.Threading;
using Xah.MediaCatalogerLib.Model;
using Xah.MediaCatalogerLib.Model.Files;

namespace Xah.MediaCatalogerLib.TreeProcess
{
    public class FolderProcessor : ICancelable
    {
        public delegate void OnProcessStepStatusCb(string name, bool stop, int index, int total);
        public event OnProcessStepStatusCb OnProcessStepStatus;

        public enum FileOperation { Add, Skip, Remove }
        public delegate void OnFileOperationCb(FileOperation operation, string path);
        public event OnFileOperationCb OnFileOperation;

        public delegate void OnFileProcessedProgressCb(int index, int total);
        public event OnFileProcessedProgressCb OnFileProcessedProgress;

        private readonly TreeFolderItem treeRoot;
        private readonly MediaCatalog db;
        private readonly MediaFolder folder;

        private ICancelable currentVisitor;
        private Thread thread;
        private bool cancelled = false;

        private int totalFileCount = 0;
        private int processedFileCount = 0;

        public bool IsFinished
        {
            get { return (thread == null) || (thread.ThreadState == ThreadState.Stopped); }
        }

        #region ICancelable Members

        public bool IsCancelled
        {
            get { return cancelled; }
        }

        public void Cancel()
        {
            cancelled = true;

            if (currentVisitor != null)
                currentVisitor.Cancel();

            if (thread != null)
                thread.Join();
        }

        #endregion

        public FolderProcessor(MediaCatalog db, MediaFolder folder)
        {
            this.db = db;
            this.folder = folder;
            this.treeRoot = new TreeFolderItem(folder.Location);
        }

        public void Process()
        {
            if (thread != null) return;

            thread = new Thread(new ThreadStart(ProcessThread));
            thread.Start();
        }

        private void ProcessThread()
        {
            const int TotalSteps = 4;
            int stepIndex = 1;
            string stepName = String.Empty;

            /////////////////////////////////////////////////////////////////
            // 1. POPULATE
            stepName = "Populate";
            FireProcessStepStatus(stepName, false, stepIndex, TotalSteps);
            
            PopulateTreeVisitor constructor = new PopulateTreeVisitor(folder.Extensions);
            currentVisitor = constructor;
            treeRoot.Accept(constructor);

            FireProcessStepStatus(stepName, true, stepIndex++, TotalSteps);
            if (IsCancelled) return;

            /////////////////////////////////////////////////////////////////
            // 2. LIST FILES
            stepName = "List Files";
            FireProcessStepStatus(stepName, false, stepIndex, TotalSteps);

            FileListerTreeVisitor lister = new FileListerTreeVisitor();
            currentVisitor = lister;
            treeRoot.Accept(lister);
            totalFileCount = lister.Files.Count;

            FireProcessStepStatus(stepName, true, stepIndex++, TotalSteps);
            if (IsCancelled) return;

            /////////////////////////////////////////////////////////////////
            // 3. REMOVE
            stepName = "Remove Non-existing Files";
            FireProcessStepStatus(stepName, false, stepIndex, TotalSteps);

            if (folder.ExistsLocation)
            {
                // Remove non existing file records related with folder
                List<string> filePaths = lister.Files.Select(x => x.Path).AsParallel().ToList();
                List<MediaFile> deleteList = folder.Files.Where(x => !filePaths.Contains(x.Path)).AsParallel().ToList();

                if (deleteList.Count > 0)
                {
                    deleteList.ForEach(x =>
                    {
                        FireFileOperation(FileOperation.Remove, x.Path);
                        x.Remove(db);
                    });

                    db.SaveChanges();
                }
            }

            FireProcessStepStatus(stepName, true, stepIndex++, TotalSteps);

            /////////////////////////////////////////////////////////////////
            // 4. ADD
            stepName = "Add New Files";
            FireProcessStepStatus(stepName, false, stepIndex, TotalSteps);

            System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew();

            AFileProcessorTreeVisitor processor = AFileProcessorTreeVisitor.Create(db, folder);
            currentVisitor = processor;
            processor.OnFileProcessed += new AFileProcessorTreeVisitor.OnFileProcessedCb(Processor_OnFileProcessed);
            treeRoot.Accept(processor);

            stopwatch.Stop();
            System.Diagnostics.Trace.TraceInformation("Add New Files FileProcessorTreeVisitor Stop ({0} elapsed)", stopwatch.Elapsed.ToString());

            FireProcessStepStatus(stepName, true, stepIndex++, TotalSteps);
        }

        private void Processor_OnFileProcessed(TreeFileItem fileItem)
        {
            processedFileCount++;
            if (OnFileProcessedProgress != null)
                OnFileProcessedProgress(processedFileCount, totalFileCount);

            FileOperation operation = (fileItem.Tag == null) ? FileOperation.Skip : FileOperation.Add;
            FireFileOperation(operation, fileItem.Path);
        }

        private void FireFileOperation(FileOperation operation, string path)
        {
            if (OnProcessStepStatus != null)
                OnFileOperation(operation, path);
        }

        private void FireProcessStepStatus(string name, bool stop, int index, int total)
        {
            if (OnProcessStepStatus != null)
                OnProcessStepStatus(name, stop, index, total);
        }
    }
}

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