If I have a domain model that looks something like this:
public class Foo<T> {
public Guid Id { get; set; }
public string Statement { get; set; }
public T Value { get; set; }
}
I want to use it for built in Data Types (string, int, etc...) as well as date. I want to use it like:
var foo = new Foo<string>();
foo.Value = "Hey";
how can I persist this to a database using EF Core?
I imagine the database table would look like
| Id | Statement | ValueAsString | ValueAsDecimal | ValueAsDate | ValueAsInt |
| 1 | NULL | "Hey" | | | |
| 2 | NULL | | 1.1 | | |
A type parameter is a placeholder for a particular type specified when creating an instance of the generic type. A generic type is declared by specifying a type parameter in an angle brackets after a type name, e.g. TypeName<T> where T is a type parameter.
Keep using EF6 if the data access code is stable and not likely to evolve or need new features. Port to EF Core if the data access code is evolving or if the app needs new features only available in EF Core. Porting to EF Core is also often done for performance.
To demonstrate the usage of Dapper, Entity Framework Core, and both combined, we will implement them each in the 3 Endpoints. For the GetAll Endpoints, we will use Dapper. The GetById Endpoint would use Entity Framework Core with Eager Loading to display the Department Details as well.
The generic repository pattern implements in a separate class library project. It uses the "Code First" development approach and creates a database from a model, using migration. This article demonstrates a sample Application, which has one too many relationships in ASP.NET Core with Entity Framework Core.
you should still have a class. Your class Foo
should be abstract.
So you would get":
public abstract class Foo<T> {
public Guid Id { get; set; }
public string Statement { get; set; }
public T Value { get; set; }
}
then your implementation class would be:
public class Orders: Foo<Order> {
}
now you have your Orders
class with your generic type which can be stored.
If you want to persist different values types to the database in a single table similar to the one in your question, you can do it like this:
public interface IHasValue<T> {
T Value { get; set; }
}
public abstract class Foo {
public Guid Id { get; set; }
public string Statement { get; set; }
}
public class Foostring : Foo, IHasValue<string> {
string Value { get; set; }
}
public class FooInt : Foo, IHasValue<int> {
int Value { get; set; }
}
In your DbContext
class add properties:
public DbSet<FooString> FooStrings { get; set: }
public DbSet<FooInt> FooInts { get; set; }
You can set the column names for the table in the OnModelCreating
method of your DbContext
:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// include the base class so a single table is created for the hierarchy
// rather than a table for each child class
modelBuilder.Entity<Foo>().ToTable("Foos");
// Specify the column names or you will get weird names
modelBuilder.Entity<FooString>().Property(entity => entity.Value)
.HasColumnName("ValueAsString");
modelBuilder.Entity<FooInt>().Property(entity => entity.Value)
.HasColumnName("ValueAsInt");
}
This code will generate a table Foos
with columns Id
, Statement
, Discriminator
, ValueAsString
and ValueAsInt
. More info on the Discrimiator
column can be found here
You still need to create a class for each Type/column you want to use for T
, I don't think you can get around that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With