How to Handle Lookup Data in C# ASP.Net MVC4

asp.net-mvc-4cclass-design

I am writing an MVC4 application to track documents we have on file for our clients. I'm using code first, and have created models for my objects (Company, Document, etc…). I am now faced with the topic of document expiration.

Business logic dictates certain documents will expire a set number of days past the document date. For example, Document A might expire in 180 days, Document 2 in 365 days, etc… I have a class for my documents as shown below (simplified for this example).

What is the best way for me to create a lookup for expiration values? I want to specify documents of type DocumentA expire in 30 days, type DocumentB expire in 75 days, etc… I can think of a few ways to do this:

  1. Lookup table in the database I can query
  2. New property in my class (DaysValidFor) which has a custom getter that returns different values based on the DocumentType
  3. A method that takes in the document type and returns the number of days

and I'm sure there are other ways I'm not even thinking of. My main concern is a) not violating any best practices and b) maintainability. Are there any pros/cons I need to be aware of for the above options, or is this a case of "just pick one and run with it"?

One last thought, right now the number of days is a value that does not need to be stored anywhere on a per-document basis — however, it is possible that business logic will change this (i.e., DocumentA's are 30 days expiration by default, but this DocumentA associated with Company XYZ will be 60 days because we like them). In that case, is a property in the Document class the best way to go, seeing as I need to add that field to the DB?

namespace Models
{
    // Types of documents to track
    public enum DocumentType
    {
        DocumentA,
        DocumentB,
        DocumentC // etc...
    }

    // Document model
    public class Document
    {
        public int DocumentID { get; set; }

        // Foreign key to companies
        public int CompanyID { get; set; }

        public DocumentType DocumentType { get; set; }

        // Helper to translate enum's value to an integer for DB storage
        [Column("DocumentType")]
        public int DocumentTypeInt
        {
            get { return (int)this.DocumentType; }
            set { this.DocumentType = (DocumentType)value; }
        }

        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:MM-dd-yyyy}", ApplyFormatInEditMode = true)]
        public DateTime DocumentDate { get; set; }


        // Navigation properties
        public virtual Company Company { get; set; }
    }
}

Best Answer

If DaysValidFor is a property of the document type, then put it in the DocumentType table, and look it up or join it with the Documents table.

If DaysValidFor can be customized, add a DaysValidFor field to the Documents table, and use the DaysValidFor in the DocumentType table as a default value when you are creating a new Document record.

Rationale

By having a DocumentType table from the start, you provide a container by which all sorts of other features become possible as a function of that document type. You also avoid a redesign when you find out you need a DocumentType table, and you didn't provide one. Not every domain object needs such a type table, but documents are naturally organized into categories, so it's a good fit here.

You can have a DaysValidFor method in your repository if you want one. Pass it the DocumentID, and look the value up from the Documents table.

If you think in terms of classes instead of tables (i.e. "code first"), just substitute the word "class" for the word "table" in the two paragraphs above.