// ========================================================================
//
// Copyright (C) 2016-2017 MARC CHEVALDONNE
//                         marc.chevaldonne.free.fr
//
// Module        : Program.cs
// Author        : Marc Chevaldonné
// Creation date : 2016-11-07
//
// ========================================================================

using static System.Console;

namespace ex_042_014_EF_CF_TPH_Inheritance
{
    /// <summary>
    /// L'approche CodeFirst d'Entity Framework vous permet de gérer l'héritage entre types de trois façons différentes :
    /// - héritage TPT (Table per Type) : une table par type (dont le type père) [PAS ENCORE IMPLEMENTE DANS ENTITY FRAMEWORK CORE]
    /// - héritage TPH (Table per Class Hierarchy) : une seule table correspondant au type père mais avec toutes les propriétés (nullables) des types fils
    /// - héritage TPC (Table per Concrete Class) : une table par type concret [PAS ENCORE IMPLEMENTE DANS ENTITY FRAMEWORK CORE]
    /// 
    /// Cet exemple montre comment mettre en oeuvre un héritage de type TPH.
    /// Ici, il n'y aura qu'une seule table correspondant à la classe mère. Toutefois, il y aura autant de colonnes que de propriétés spécifiques dans les classes filles.
    /// Les valeurs seront nullables : si l'objet est de type A, toutes valeurs des colonnes correspondant au type B seront nulles.
    /// 
    /// Pour la mettre en oeuvre, il suffit de ne rien faire ! Il ne faut utiliser aucune annotations de données sur les classes filles, et ne pas utiliser la fluent API pour les classes filles.
    /// Dans l'exemple suivant, les types fils (Rectangle et Cercle) n'utilisent aucune annotation de données ([Table("Rectangles")] et [Table("Cercles")]) et aucune ligne de code en fluent API dans la classe DbContext.
    /// 
    /// Notez bien que la classe qui dérive de DbContext ne contient qu'un DbSet de Forme.
    /// 
    /// Après avoir exécuté l'exemple, vous pouvez vous rendre dans l'explorateur d'objets SQL Server, et constater qu'Entity Framework a créé une seule table (Formes).
    /// Notez la présence de la colonne Discriminator qui indique quel est le type concret de l'objet correspondant à la ligne.
    /// Notez également la présence des colonnes Longueur et Largeur (pourtant spécificiques à Rectangle) et Rayon (pourtant spécifique à Cercle) qui ont des valeurs nulles si le type fils n'a pas ces propriétés.
    /// </summary>
    public class Program
    {
        public static void Main(string[] args)
        {
            //création du DbContext et injection de la dépendance à MyStubDataInitializationStrategy
            using (FormesDBEntities db = new FormesDBEntities())
            {
                //choix de la stratégie et remplissage avec des données stubbées
                DbContextInitializer.Seed(db);

                WriteLine("formes : ");
                foreach (var f in db.FormesSet)
                {
                    WriteLine($"\t{f}");
                }
            }
        }
    }
}
