locked
Inheritance In Code First Approach RRS feed

  • Question

  • User1928065626 posted

    Suppose I am implementing the Repository and Unit Of Work Pattern in my project so that I can unit test my methods. The following are folders of interest inside the project folder

    // Core - contains Domain and Repository folders
    
    // Domain folder contains the following classes 
           
           public abstract class Account
           {
           }
           public class CheckingAccount:
           {
           }
           public class SavingsAccount:
           {
           }
    
           Repository folder contains IUnitOfWork interface with the following details
           public interface IUnitOfWork:: IDisposable
           {
               IAccountRepository Accounts{ get; }
               ICheckingRepository CheckingAccounts{ get; }
               ISavingsRepository SavingsAccounts { get; }
               int Complete();
           }
    
    // Persistent - contains Repositories folder, CheckingAccountRepository, SavingsAccountRepository, and BankContext class 
    
    // I will only focus on the BankContext and UnitOfWork classes        
    
           public class UnitOfWork : IUnitOfWork
           {
              private readonly BankContext _context;
    
              public UnitOfWork(BankContext context)
              {
                _context = context;
                CheckingsAccount = new CheckingRepository(_context);
                SavingsAccount = new SavingsRepository(_context);
              }
    
              public ICheckingRepository Checkings { get; private set; }
              public ISavingsRepository Savingss { get; private set; }
    
              public int Complete()
              {
                return _context.SaveChanges();
              }
    
              public void Dispose()
              {
                _context.Dispose();
              }
           }
    
           public class BankContext : DbContext
           {
              public BankContext()
              : base("name=BankContext")
              {
                this.Configuration.LazyLoadingEnabled = false;
              }
    
              public virtual DbSet<Account> Accounts { get; set; }
              public virtual DbSet<CheckingAccount> CheckingAccounts { get; set; }
              public virtual DbSet<SavingsAccount> SavingsAccounts { get; set; }
    
              protected override void OnModelCreating(DbModelBuilder modelBuilder)
              {
                modelBuilder.Configurations.Add(new AccountConfiguration());
              }
           }

    In the code above, I have an abstract class called Account which serves as the base class for CheckingAccount and SavingsAccount classes.

    The code in the Repository folder and Persistent folder above are what my code would look like if all the classes in the Domain folder are concrete classes

    The question I would like to ask is since the Account class in the Domain folder is an abstract class, how does it affect the code for Accounts property in the Repository folder and the code in the BankContext class in the Persistent folder.

    Friday, December 23, 2016 9:29 PM

All replies

  • User-271186128 posted

    Hi madjester,

    The question I would like to ask is since the Account class in the Domain folder is an abstract class, how does it affect the code for Accounts property in the Repository folder and the code in the BankContext class in the Persistent folder.

    In Code First, the default inheritance mapping strategy is TPH(Table Per Hierarchy). An entire class hierarchy can be mapped to a single table.

    This table includes columns for all properties of all classes in the hierarchy. The concrete subclass represented by a particular row is identified by the value of a type discriminator column.

    For example :

    Account class is base class.

    public abstract class Account
        {
            [Key]
            public int ID { get; set; }
            public abstract int x { get; set; }
      }
    
    public class AAccount : Account
        {
            public string A { get; set; }
    
            public override int x
            {
                get
                {
                    throw new NotImplementedException();
                }
    
                set
                {
                    throw new NotImplementedException();
                }
            }
        }
    
    public class BAccount : Account
        {
            public string B { get; set; }
    
            public override int x
            {
                get
                {
                    throw new NotImplementedException();
                }
    
                set
                {
                    throw new NotImplementedException();
                }
            }
    }
    

    The table generate by code first is:

    And the abstract int x will not be include in the table. 

    There also has other strategy in code first. For more information, you can refer to this link:

    http://www.entityframeworktutorial.net/code-first/inheritance-strategy-in-code-first.aspx 

    Best regards,
    Billy

     

    Monday, December 26, 2016 10:11 AM
  • User1928065626 posted

    Hi, thank you so much for replying. I was aware of the different inheritance strategies that one can use with Entity Framework and I was planning to go with Table Per Type (TPT) strategy instead of Table per Hierachy (TPH).

    However, my question still hasn't been answered. How can I implement Repository and UnitOfWork patterns when TPH or TPT is used?

    Monday, December 26, 2016 3:59 PM
  • User-271186128 posted

    Hi madjester,

    If you want to use TPT, please set the ctx class like this:      

    public class BankContext : DbContext
    {
    public BankContext()
      : base("name=BankContext")
    {
         Database.SetInitializer<BankContext>(null);
    }
    public DbSet<Account> Account { get; set; }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
    modelBuilder.Entity<SavingsAccount>().ToTable("Savings");
    modelBuilder.Entity<CheckingAccount>().ToTable("Checking");
    }
    }

    And you can refer to below link to implement Repository and UnitOfWork patterns.

    https://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

    Best Regards,
    Billy

    Friday, December 30, 2016 9:19 AM