是否可以在不使用中间 类 的情况下访问 EF Core 中的共享 TPH 列?

Is it possible to access a shared TPH column in EF Core without using intermediate classes?

在 EF Core TPH 设置中使用 shared columns 时,是否可以在投影期间访问共享列

    class Program
    {
        public static readonly ILoggerFactory MyLoggerFactory
            = LoggerFactory.Create(builder => { 
                builder.AddConsole(); 
            });

        static async Task Main(string[] args)
        {
            using (var context = new ClientContext())
            {
                context.Database.EnsureDeleted();
                context.Database.EnsureCreated();

                var actions = await context.Actions
                    .Select(a => new
                    {
                        Id = a.Id,

                        // this works - but really messy and complex in real world code
                        Message = (a as ActionA).Message ?? (a as ActionB).Message,

                        // this throws "Either the query source is not an entity type, or the specified property does not exist on the entity type."
                        // is there any other way to access the shared column Message?
                        // Message = EF.Property<string>(a, "Message"),
                    })
                    .ToListAsync();

                actions.ForEach(a => Console.WriteLine(a.Id + a.Message));
            }
        }

        public class ActionBase
        {
            public int Id { get; set; }

            // ... other shared properties
        }

        public class ActionA : ActionBase
        {
            // shared with B
            [Required]
            [Column("Message")]
            public string Message { get; set; }

            // ... other specific properties
        }

        public class ActionB : ActionBase
        {
            // shared with A
            [Required]
            [Column("Message")]
            public string Message { get; set; }

            // ... other specific properties
        }

        public class ActionC : ActionBase
        {
            public string SomethingElse { get; set; }

            // ... other specific properties
        }

        class ClientContext : DbContext
        {
            protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            {
                // TO USE SQL
                //optionsBuilder
                //    .UseLoggerFactory(MyLoggerFactory)
                //    .UseSqlServer("Server=(localdb)\mssqllocaldb;Database=TPHSharedColumn;Trusted_Connection=True;MultipleActiveResultSets=true;Connect Timeout=30")
                //    .EnableSensitiveDataLogging(false);
                // TO USE INMEMORY
                optionsBuilder
                   .UseLoggerFactory(MyLoggerFactory)
                   .UseInMemoryDatabase(Guid.NewGuid().ToString());
            }

            protected override void OnModelCreating(ModelBuilder builder)
            {
                base.OnModelCreating(builder);

                builder.Entity<ActionA>().HasData(new ActionA()
                {
                    Id = 1,
                    Message = "A"
                });
                builder.Entity<ActionB>().HasData(new ActionB()
                {
                    Id = 2,
                    Message = "B"
                });
                builder.Entity<ActionC>().HasData(new ActionC()
                {
                    Id = 3,
                    SomethingElse = "C"
                });
            }

            public DbSet<ActionBase> Actions { get; set; }
        }
    }

在这个简单的示例中,当然可以将 Message 移动到基数 class - 但是这可能会不小心添加 ActionCMessage 因为我需要删除 Required 属性。

我也知道我可以添加一个 ActionWithRequiredMessage 中间体 class 来继承 ActionAActionB,但同样 - 在更复杂的现实世界示例中这是不可行的,因为还有其他共享列,并且 C# 不允许从多个 classes 继承 - EF Core 似乎不喜欢为此使用接口。

我只是想找到一种方法来直接访问共享列 - 并在投影中使用它。

有人知道这是否可行吗?

我找不到它的文档,但在 EF Core 5.x 中,您可以使用具有 [=19= 的派生实体的 any 访问共享列] 映射到它,例如所有这些工作

Message = (a as ActionA).Message,
Message = (a as ActionB).Message,
Message = ((ActionA)a).Message,
Message = ((ActionB)a).Message,