摘要
我正在尝试将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
。
我有以下简单的数据库架构:
我的课程如下:
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!
}
}
}
}
感谢您的帮助