简体   繁体   中英

Entity Framework Core - Inherited Object Types and Dynamic Table Names

I have a list of tables that are partitioned. There are lots of these tables but with the same structure. Realize that EF core requires different types for these, but eventually I'd like to use a generic cast on the data, would make it easier to work with the data. Working with Oracle, but think questions would apply generically.

Here's the error. Basically I want to cast a DbSet of T to a DbSet of S where S is the parent class of T.

System.InvalidCastException: 'Unable to cast object of type 'Microsoft.EntityFrameworkCore.Internal.InternalDbSet 1[EfCoreBidTest.BidPhaseLh2]' to type 'Microsoft.EntityFrameworkCore.DbSet 1[EfCoreBidTest.BidPhase]'.'

Keep in mind, I'll be working with multiple inherited types at a time of the same base.

Here's a base class example:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;

namespace EfCoreBidTest
{
    public class BidPhase
    {
        [Column("YR")]
        public int Yr { get; set; }

        [Column("QTR")]
        public string Qtr { get; set; }

        [Column("AMB_CODE")]
        public string AmbCode { get; set; }

        [Column("SECT")]
        public string Sect { get; set; }

        [Column("PHASE_ITEM")]
        public int PhaseItem { get; set; }

        [Column("PHASE")]
        public string Phase { get; set; }

        [Column("PHASE_DATE")]
        public DateTime? PhaseDate { get; set; }
    }
}

and an inherited class (there will be lots of these)

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;

namespace EfCoreBidTest
{
    [Table("BID_LH2_MASTSTAT_PHASE")]
    public class BidPhaseLh2 : BidPhase
    {
    }
}

Trying to create a generic method on the DbContext to get a phase object type, that's when I receive the error

    public DbSet<BidPhase> GetPhaseSet(string sys, string stage)
    {

        var t = typeof(BidDatabase);

        var setMethod = t.GetMethod("Set");
        var setMethodSpecific = setMethod.MakeGenericMethod(new Type[] { typeof(BidPhaseLh2) }); // TO DO - This will eventually get replaced with something to get the type based on the assembly name
        var dbSet = setMethodSpecific.Invoke(this, null);
        return (DbSet <BidPhase> ) dbSet;


        //sys = Char.ToUpper(sys[0]) + sys.Substring(1).ToLower();
        //return (IQueryable<BidPhase>) this.GetType().GetProperty("BidPhase" + sys + stage).GetValue(this);
    }

A DbSet<BidPhase> is a completely different type to DbSet<BidPhase2> , even if the generic types inherit from each other - DbSet<> isn't covariant . One way round this would be to use IQueryable<> instead of DbSet<> . For example:

public static IQueryable<BidPhase> GetPhaseSet(BidDatabase ctx)
{
    var t = typeof(BidDatabase);

    var setMethod = t.GetMethod("Set");
    var setMethodSpecific = setMethod.MakeGenericMethod(new Type[] { typeof(BidPhaseLh2) }); 
    var dbSet = setMethodSpecific.Invoke(ctx, null);
    return (IQueryable<BidPhase>)dbSet;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM