Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I implement a simple "complex type" in Entity Framework Core 2/C#?

I'm using Entity Framework and .Net Core 2.0 for the first time (I'm also pretty new to C#, but I've been using the traditional .Net Framework & VB since version 1... so I'm no newbie to .Net development), and I've already run into a problem creating my database.

Take this simple scenario: I want to store some information about some electric pumps. Two of the properties are a min/max type range, so I've implemented these as a simple class, thus:

public class Pump
{
    [Key]
    public int pumpId { get; set; }
    public string pumpName { get; set; }
    public int pumpControlChannel { get; set; }
    public MinMax normalCurrent { get; set; }
    public MinMax normalFlowRate { get; set; }
}

[ComplexType]
public class MinMax
{
    public int min { get; set; }
    public int max { get; set; }
}

As you can see, I've tried the [ComplexType] decorator, to no avail.

Anyway, now create a dead simple DBContext class to manage my Pumps class. I'm using Sqlite:

public class EFDB : DbContext
{
    public DbSet<Pump> pumps { get; private set; }

    private static DbContextOptions GetOptions(string connectionString)
    {
        var modelBuilder = new DbContextOptionsBuilder();
        return modelBuilder.UseSqlite(connectionString).Options;
    }

    public EFDB(string connectionString) : base(GetOptions(connectionString)) { }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        try
        {
            // modelBuilder.ComplexType<MinMax>();      // ComplexType not recognised
            base.OnModelCreating(modelBuilder);
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debugger.Break();
        }
    }

}

and lastly a simple static class to call it (I embeded it in a bigger program... to duplicate this problem you could just stick the code lines into program.cs):

public static class TryMe
{
    public static void MakeMeFail()
    {
        using (var db = new EFDB("FileName=C:\\temp\\test_effail.db"))
        {
            try
            {
                db.Database.EnsureCreated();
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debugger.Break();   // If we hit this line, it fell over
            }
        }
        System.Diagnostics.Debugger.Break();   // If we hit this line, it worked.
    }
}

Just call TryMe.MakeMeFail(), the code fails at db.Database.EnsureCreated().

From everything I've read, [ComplexType] should do what I want... but it Just Doesn't. Nor can I find modelBuilder.ComplexType<T> anywhere.

It may just be a library reference I'm missing...? The above code uses the following:

using System;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

However, NONE of the documentation/examples I can find anywhere show which libraries need referencing!

Thanks in advance.

[PS: Apologies to those who already saw this question, I'm using EF Core 2.0, NOT EF6]

like image 362
Ade Avatar asked May 28 '18 18:05

Ade


People also ask

How do I add complex type to Entity Framework?

Right-click an entity, point to Add New, and select Complex Property. A complex type property with a default name is added to the entity.

What is a complex type C#?

A complex type is a set of properties that exist in its own object for C#, but are mapped to columns on an already existing table (the one for the entity that contains it), instead of having its own table (which would need a key, etc.).

Which method is used to apply configuration to entities or their properties in the Entity Framework Core?

Property Mapping. The Property method is used to configure attributes for each property belonging to an entity or complex type.

Which approach is best in Entity Framework?

As in this diagram, if we already have domain classes, the Code First approach is best suited for our application. The same as if we have a database, Database First is a good option. If we don't have model classes and a database and require a visual entity designer tool then Model First is best suited.


1 Answers

Typical... it's always the way, isn't it? 5 minutes after posting, you discover the answer to your own question....

The answer, in this case, can be found here:

https://learn.microsoft.com/en-us/ef/core/modeling/owned-entities

EF Core calls this sort of entity an "owned" entity, rather than a "complex type".

Simply adding these lines to `OnModelCreating' fixed the issue:

modelBuilder.Entity<Pump>().OwnsOne(p => p.normalCurrent);
modelBuilder.Entity<Pump>().OwnsOne(p => p.normalFlowRate);

The database now creates (correctly, I think, I haven't verified that yet).

like image 57
Ade Avatar answered Oct 22 '22 14:10

Ade