I'm always having the problem on how to properly design having static
entity instances and it being attached to Entity Framework's Dbcontext
. For example, we have the following:
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using Xunit;
namespace ClassLibrary1
{
public class PersonType
{
public static readonly PersonType Student = new PersonType(1, "Student");
public static readonly PersonType Teacher = new PersonType(2, "Teacher");
public PersonType(int personTypeId, string description)
{
PersonTypeId = personTypeId;
Description = description;
}
public int PersonTypeId { get; set; }
public string Description { get; set; }
}
public class MyContext : DbContext
{
public DbSet<PersonType> PersonTypes { get; set; }
public MyContext(DbContextOptions<MyContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<PersonType>(builder =>
{
builder.HasData(
PersonType.Student,
PersonType.Teacher);
});
}
}
public class Tests
{
[Fact]
public void This_test_fails()
{
var options = new DbContextOptionsBuilder<MyContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
using (var ctx = new MyContext(options))
ctx.Database.EnsureCreated();
using (var ctx = new MyContext(options))
{
//call Attach to pass
//ctx.Attach(PersonType.Student);
Assert.Equal(
PersonType.Student,
ctx.PersonTypes.First(p => p.Description == "Student"));
}
}
}
}
The reason I need the static entity classes is for functions with logic based on PersonType
(e.g. if(personType == PersonType.Student)
. To make this work, I need to call DbContext.Attach
(which is easy to forget to call) so the context's PersonType
will be equal to its corresponding static instance.
Is calling Attach
the only way to solve this? Or is there something wrong with my design choices?
I'm primarily using EF Core but I believe this scenario is also present to EF6.
There is this open feature request issue in EF Core which would solve this problem but it seems not many people encounter this scenario so I'm thinking there's a different way to design this.
EDIT: There is a PersonType
s table in the database which is related to other tables.
Best Answer
The current implementation requires that you recompile the application if you later want to add teaching assistants. So that you might as well use Enums if you do not want to store the person types in the database.
Personally I would create a person type table in the database.
Secondly I would revisit the decision that you actually need to know, outside of the person class that is, which person type a person is. You should tell an instance of a class to do an action, not check what person type a person is and then decide what to do with the person.