Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework Code First - One Table / Multiple Types

In my database I have created a table similar to this:

dbo.Words
    WordId INT PRIMARY KEY
    WordText NVARCHAR(75)
    WordTypeId INT FK

WordTypeId references another table which is a lookup. It will have one of the following values:

Verb
Noun
Adjective

I would like to create entity classes like this:

public class Word
{ ... }

public class Noun : Word
{ ... }

public class Verb : Word
{ ... }

public class WordType
{ ... }

public class MyContext : DbContext
{
    public DbSet<Noun> Nouns { get; set; }
    public DbSet<Verb> Verbs { get; set; }
    public DbSet<Word> Words { get; set; }
    public DbSet<WordType> WordTypes { get; set; }
}

How would I accomplish this in Entity Framework 4.1 - Code First? When I query the Nouns DbSet I want it to only return words with WordTypeId of whatever my Noun type is in the WordTypes table.

like image 987
Dismissile Avatar asked Sep 12 '11 20:09

Dismissile


People also ask

How will you create relationship between tables in Entity Framework?

You can create such a relationship by defining a third table, called a junction table, whose primary key consists of the foreign keys from both table A and table B.

What is table splitting in Entity Framework?

EF Core allows to map two or more entities to a single row. This is called table splitting or table sharing.

How do you create a foreign key relationship in code first approach?

To create Foreign Key, you need to use ForeignKey attribute with specifying the name of the property as parameter. You also need to specify the name of the table which is going to participate in relationship. I mean to say, define the foreign key table. Thanks for reading this article, hope you enjoyed it.


1 Answers

You need to adopt Table per Hierarchy (TPH) where ehe entire hierarchy is mapped to a single database table (dbo.Words) holding all the properties of all the classes and use the WordTypeId column as a Discriminator column .. here you go.

1. Domain Model

public abstract class Word
{
    public int WordId { get; set; }
    public string WordText { get; set; }
    //DO NOT map the WordTypeId column
    //as it is used as the Discriminator column
}

public class Noun : Word { }
public class Verb : Word { }
public class Adjective : Word { }

2. Context

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    //Assuming WordTypeId eqauls 1 for Nouns, 2 for Verbs, 3 for Adjectives
    modelBuilder.Entity<Noun>().Map<Word>(c => c.Requires("WordTypeId").HasValue(1));
    modelBuilder.Entity<Verb>().Map<Word>(c => c.Requires("WordTypeId").HasValue(2));
    modelBuilder.Entity<Adjective>().Map<Word>(c => c.Requires("WordTypeId").HasValue(3));
}

To get your verbs use :

var verbs = x.Words.OfType<Verb>()
like image 147
Hossam Avatar answered Sep 23 '22 08:09

Hossam