EF Core - 父母和子女继承中的一对多

时间:2017-11-16 20:29:48

标签: c# entity-framework inheritance entity-framework-core

摘要

我正在尝试将Table Per Hierarchy继承与.Net Core 1.1项目中的一对多关系结合使用。父实体和子实体都使用继承。 我有一个非常简单的实体模型。我有一个基本的父实体:会话,它有两个从中扩展的实体: QuotingSession BackOfficeSession 。这两个父实体都包含子实体的集合(一对多关系)。子实体也使用继承构建。有一个基本子实体:政策。此基本子实体由两个实体扩展: QuotingPolicy和BackOfficePolicy 。当我构造任一父实体并尝试保存时,我收到此异常:

InvalidCastException: Unable to cast object of type 'EFTest.QuotingSession' to type 'EFTest.BackOfficeSession

但是,当我告诉实体框架忽略父项中任何一个子集合时,保存对两个父实体都有效,没有异常。例如:

 var entity = modelBuilder.Entity<BackOfficeSession>();
 entity.Ignore(c => c.Policies); 

此外,如果我根本没有配置其中一个Parent(QuotingSession),只保存另一个Parent(BackOfficeSession),则所有内容都保存为例外。

回购

https://github.com/seantarogers/EFTest

详情

我在Microsoft.EntityFrameworkCore 1.1.1项目中使用Microsoft.EntityFrameworkCore.SqlServer 1.1.1.Net core 1.1

我有以下简单的数据库架构:

enter image description here

我的课程如下:

1。会话

namespace EFTest
{
    public abstract class Session
    {
        public int Id { get; private set; }
    }
}

2。 QuotingSession

using System.Collections.Generic;

namespace EFTest
{
    public class QuotingSession : Session
    {
        public string QuotingName { get; private set; }
        public List<QuotingPolicy> Policies { get; private set; }

        private QuotingSession()
        {
        }

        public QuotingSession(string name, List<QuotingPolicy> quotingPolicies)
        {
            QuotingName = name;
            Policies = quotingPolicies;

        }
   }
}

第3。 BackOfficeSession

using System.Collections.Generic;

namespace EFTest
{
    public class BackOfficeSession : Session
    {
        public List<BackOfficePolicy> Policies { get; private set; }
        public string BackOfficeName { get; private set; }

        private BackOfficeSession()
        {
        }

        public BackOfficeSession(string name, List<BackOfficePolicy> policies)
        {
            BackOfficeName = name;
            Policies = policies;
        }
    }
}

4。政策

namespace EFTest
{
    public abstract class Policy
    {
        public int Id { get; set; }
        public int SessionId { get; set; }
    }
}

5。 QuotingPolicy

namespace EFTest
{
    public class QuotingPolicy : Policy
    {
        public string QuotingPolicyName { get; private set; }

        private QuotingPolicy()
        {

        }

        public QuotingPolicy(string name)
        {
            QuotingPolicyName = name;
        }
    }
}

6。 BackOfficePolicy

namespace EFTest
 {
    public class BackOfficePolicy : Policy
    {
        public string BackOfficePolicyName { get; private set; }

        private BackOfficePolicy()
        {
        }

        public BackOfficePolicy(string name)
        {
           BackOfficePolicyName = name;
        }
    }
}

7。 EF DB上下文和流畅配置

using Microsoft.EntityFrameworkCore;

namespace EFTest
{
    public class TestDbContext : DbContext
    {
        public TestDbContext(DbContextOptions options)
        : base(options)
        {
        }

        public DbSet<QuotingSession> QuotingSessions { get; set; }
        public DbSet<BackOfficeSession> BackOfficeSessions { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            ConfigureSession(modelBuilder);
            ConfigurePolicy(modelBuilder);
            ConfigureQuotingSession(modelBuilder);
            ConfigureBackOfficeSession(modelBuilder);
            ConfigureBackOfficePolicy(modelBuilder);
            ConfigureQuotingPolicy(modelBuilder);
        }

        public static void ConfigurePolicy(ModelBuilder modelBuilder)
        {
            var entity = modelBuilder.Entity<Policy>();
            entity.ToTable("Policy", "dbo");
            entity.HasKey(x => x.Id);

            entity.HasDiscriminator<int>("SessionType")
                .HasValue<QuotingPolicy>(1)
                .HasValue<BackOfficePolicy>(2);
        }

        public static void ConfigureBackOfficePolicy(ModelBuilder modelBuilder)
        {
            var entity = modelBuilder.Entity<BackOfficePolicy>();
            entity.Property(x => x.BackOfficePolicyName);
        }

        public static void ConfigureQuotingPolicy(ModelBuilder modelBuilder)
        {
            var entity = modelBuilder.Entity<QuotingPolicy>();
            entity.Property(x => x.QuotingPolicyName);
        }

        public static void ConfigureSession(ModelBuilder modelBuilder)
        {
            var entity = modelBuilder.Entity<Session>();
            entity.ToTable("Session", "dbo");
            entity.HasKey(x => x.Id);

            entity.HasDiscriminator<int>("SessionType")
                .HasValue<QuotingSession>(1)
                .HasValue<BackOfficeSession>(2);
        }

        public static void ConfigureBackOfficeSession(ModelBuilder modelBuilder)
        {
            var entity = modelBuilder.Entity<BackOfficeSession>();
            entity.Property(x => x.BackOfficeName);
            entity.HasMany(c => c.Policies).WithOne().HasForeignKey(c => c.SessionId);
       // entity.Ignore(c => c.Policies); uncomment this to see it working
        }

        public static void ConfigureQuotingSession(ModelBuilder modelBuilder)
        {
            var entity = modelBuilder.Entity<QuotingSession>();
            entity.Property(x => x.QuotingName);
            entity.HasMany(c => c.Policies).WithOne().HasForeignKey(c => c.SessionId);
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
        }
    }
}

8。测试

using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;

namespace EFTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var optionsBuilder = new DbContextOptionsBuilder<TestDbContext>();
            const string conn = "Server=.\\SqlServer2014;Database=EFTest;Trusted_Connection=True"    
            optionsBuilder.UseSqlServer(conn);
            using (var dbContext = new TestDbContext(optionsBuilder.Options))
            {
                var quotingPolicy = new QuotingPolicy("quotingPolicyname");
                var quotingSession = new QuotingSession("quotingSessionName", new List<QuotingPolicy> {quotingPolicy});

                dbContext.QuotingSessions.Add(quotingSession);
                dbContext.SaveChanges();  // BLOWS UP HERE!
           }
        }
    }
}

感谢您的帮助

0 个答案:

没有答案