File Audit with Entity Framework: Retrieve and Check Missing Files with Closest Modification Date

Introduction:

In this article, we will discuss a method named FileAudit which is used to retrieve file names from a database table using Entity Framework and checks if these files exist in a specified directory. If a file is missing, it finds the file with the closest modification date to the target date and returns information about the missing file. We will also discuss the supporting methods, including GetParent and GetClosestFile.

The code:

// This method returns an ActionResult for FileAudit with an optional parameter of max that defaults to 10 if not specified.
        public ActionResult FileAudit(int max = 300000)
        {

            // Retrieve file names from the database table using Entity Framework
            var attachments = db.Attachments.OrderByDescending(i=>i.ChangeDate).Take(max).ToList();

            // Get the path of the directory where the images are stored
            string CurrentDir = HttpContext.Server.MapPath("~/Images/");

            // Create a new instance of DirectoryInfo class with the specified path
            var directoryInfo = new DirectoryInfo(CurrentDir);

            // Get the list of files in the directory
            var files = directoryInfo.GetFiles();

            // Create a list to store the missing files
            List<MissingFiles> missingFiles = new List<MissingFiles>();

            // Iterate through the list of file names retrieved from the database
            foreach (var attachment in attachments)
            {
                // Get the full path of the file
                string filePath = CurrentDir + attachment.ImageFilePath;

                // Check if the file exists
                if (!System.IO.File.Exists(filePath))
                {
                    // If the file doesn't exist, get the closest file based on the modification date
                    var closestfile = GetClosestFile(attachment.ChangeDate ?? attachment.Date, files);

                    // Add the missing file information to the missingFiles list
                    missingFiles.Add(new MissingFiles()
                    {
                        id = attachment.ID,
                        ParentRecord = GetParent(attachment),
                        FilePath =attachment.ImageFilePath,
                        ChangeDate = attachment.ChangeDate ?? attachment.Date,
                        FileWithClosestDateName = closestfile.Name,
                        DateOfClosestFile = closestfile.LastWriteTime,
                        Found = false,
                        TimeOffSet = ((attachment.ChangeDate ?? attachment.Date) - closestfile.LastWriteTime),

                    });
                }
            }

            // Return a view with the list of missing files
            return View(missingFiles);
        }
        public Parent GetParent(Attachment a)
        {
            var id = a.EpisodeID ?? a.FacilityID??a.ContactID??a.PersonID??a.PhoneCommID;
            Parent p = new Parent() {  id = id };

            var parents = new List<Object>() { a.Episode,a.Facility,a.Contact,a.Person,a.PhoneCommunication};
            foreach (object item in parents)
            {
                if (item != null)
                {
                    Console.WriteLine("The type of the non-null object is: " + item.GetType());
                    p.ParentType = item;
                    break;
                }
            }
            return p;
        }
        

        // This method returns the file with the closest modification date to the target date
        public static FileInfo GetClosestFile(DateTime targetDate, FileInfo[] files)
        {
            // Find the file with the closest modification date to the target date
            var closestFile = files.OrderBy(file => Math.Abs((file.LastWriteTime - targetDate).Ticks)).FirstOrDefault();

            return closestFile;
        }

And here is the view:

@model IEnumerable<WebApplication3.Models.MissingFiles>


<h2>Missing Files</h2>
<form id="myForm" method="GET" action="@Url.Action("FileAudit")">
    <label for="max">Enter value to set a max limit to files checked:</label>
    <input type="number" id="max" name="max" required>
    <button type="submit">Submit</button>
</form>

<table id="missing-files-table" class="table">
    <thead>
        <tr>
            <th>File Name</th>
            <th>Parent</th>
            <th>ChangeDate</th>

            <th>Found</th>
            <th>Date of Closest File</th>
            <th>File with Closest Date Name</th>
            <th>Time difference</th>
            <th>Delete</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var file in Model)
        {
            <tr>
                <td>@file.FilePath</td>

                <td>
                    @if (file.ParentRecord.ParentType is WebApplication3.Models.Episode)
                    {
                        <a class="btn btn-primary  glyphicon glyphicon-share" href="/Episode/EditPartial_Blank/@file.ParentRecord.id" target="_blank"
                           title="Open Episode in a new page">

                        </a>
                    }
                    @if (file.ParentRecord.ParentType is WebApplication3.Models.Facility)
                    {

                        <a onclick="GenericEditModal('Facility/EditFacilityPartial/', 'EditFacilityModal', 'EditFacilityModalPlaceholder', 'EditFacilityForm',
    @file.ParentRecord.id)">Edit</a>
                    }
                    @if (file.ParentRecord.ParentType is WebApplication3.Models.PhoneCommunication)
                    {

                        <a class="btn btn-xs btn-primary glyphicon glyphicon-share" href="/PCommsSwitches/Details/@file.ParentRecord.id" target="_blank" title="View Details in new window">
                        </a>
                    }

                </td>

                <td>@file.ChangeDate</td>

                <td>@(file.Found ? "Yes" : "No")</td>
                <td>@file.DateOfClosestFile</td>
                <td>@file.FileWithClosestDateName</td>
                <td>@file.TimeOffSet</td>
                <td><a href="Delete/@file.id" target="_blank">Delete</a></td>

            </tr>
        }
    </tbody>
</table>

@section Scripts {
    <script>
        $(document).ready(function () {
            $.fn.dataTable.moment('DD-MM-YYYY');

            $('#missing-files-table').DataTable({
                dom: 'Bfrtip',
                buttons: [
                    'excelHtml5'
                ]
            });
        });</script>
}

Method Description:

The FileAudit method is defined as a public ActionResult method, which returns an optional parameter of max with a default value of 300000 if it is not specified. Inside the method, it retrieves the file names from the database table using Entity Framework and orders them by the ChangeDate in descending order. It then takes the specified number of files (or the default value) and stores them in a list named attachments.

Next, it gets the path of the directory where the images are stored using the HttpContext.Server.MapPath method. It then creates a new instance of the DirectoryInfo class with the specified path and gets the list of files in the directory using the GetFiles method.

A list named missingFiles is created to store the missing files. The method then iterates through the list of file names retrieved from the database and checks if the file exists in the directory using the System.IO.File.Exists method. If the file does not exist, it calls the GetClosestFile method to get the closest file based on the modification date.

The missing file information, including the file ID, the parent record, file path, change date, the name of the closest file, the date of the closest file, whether the file is found or not, and the time offset is then added to the missingFiles list.

Finally, the method returns a view with the list of missing files.

Supporting Methods:

  1. GetParent: This method takes an Attachment object as a parameter and returns a Parent object. It first gets the ID of the parent record from the attachment object. It then creates a Parent object with the retrieved ID and checks which parent type the attachment belongs to by iterating through a list of parent objects. It then sets the ParentType property of the Parent object to the first non-null parent type and returns the Parent object.
  2. GetClosestFile: This method takes a DateTime targetDate and a FileInfo[] files as parameters and returns the file with the closest modification date to the target date. It first orders the files by the absolute difference between the file’s LastWriteTime property and the target date. It then returns the closest file.

Conclusion:

In conclusion, the FileAudit method is a useful method that retrieves file names from a database table and checks if these files exist in a specified directory. It provides information about the missing files and the closest file based on the modification date. The supporting methods, including GetParent and GetClosestFile, make the method more versatile and useful.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *