如何Include
集合类型为每个层次结构表设计的集合上的属性关系,以及在延迟加载禁用的派生类型上定义关系?
我要避免的是在基类型上声明关系或者有多个DB调用来检索关系。有办法解决这个问题吗?
我已尝试使用OfType
但收到此消息。
System.ArgumentException - Include路径表达式必须引用在类型上定义的导航属性。使用虚线路径作为参考导航属性,使用Select运算符作为集合导航属性。
我尝试使用as
但收到此错误
System.InvalidOperationException - 指定的包含路径无效。 EntityType' Sandbox.TPHMcve.Person'不会声明名称为' Buildings'。
的导航属性
请不要关注这个愚蠢的例子的商业细节,这是一个说明我收到的错误的mcve。我的实际项目与学校/学校系统等无关。
SchoolService.cs
这是产生例外的实际感兴趣的代码
public sealed class SchoolService
{
private readonly UniversityDbContext _dbContext;
public SchoolService(UniversityDbContext dbContext)
{
_dbContext = dbContext;
}
public School GetSchoolAndPeopleWithDetails_OfType(int schoolId)
{
return _dbContext.Schools.Where(x => x.SchoolId == schoolId)
.Include(x => x.EntitiesOfSchool.OfType<Teacher>().Select(y => y.Buildings))
.Include(x => x.EntitiesOfSchool.OfType<Student>().Select(y => y.BooksOnLoan))
.SingleOrDefault();
}
public School GetSchoolAndPeopleWithDetails_Cast(int schoolId)
{
return _dbContext.Schools.Where(x => x.SchoolId == schoolId)
.Include(x => x.EntitiesOfSchool.Select(y => (y as Teacher).Buildings))
.Include(x => x.EntitiesOfSchool.Select(y => (y as Student).BooksOnLoan))
.SingleOrDefault();
}
}
Entities.cs
public sealed class School
{
public int SchoolId { get; set; }
public string Name { get; set; }
public List<Person> EntitiesOfSchool { get; set; }
}
public abstract class Person
{
public int PersonId { get; set; }
public string Name { get; set; }
public School PrimarySchool { get; set; }
public int SchoolId { get; set; }
}
public sealed class Teacher : Person
{
public ICollection<Building> Buildings { get; set; }
}
public sealed class Student : Person
{
public ICollection<CourseBook> BooksOnLoan { get; set; }
}
public sealed class Building
{
public int BuildingId { get; set; }
public string Name { get; set; }
public Teacher AssignedGuardian { get; set; }
public int GuardianId { get; set; }
}
public sealed class CourseBook
{
public int CourseBookId { get; set; }
public int BookNumber { get; set; }
public Student AssignedTo { get; set; }
public int? AssignedToId { get; set; }
}
EntityMappings.cs 不包含Building或CourseBook映射类型,因为它们不相关
public sealed class SchoolMap : EntityTypeConfiguration<School>
{
public SchoolMap()
{
ToTable("Schools");
HasKey(x => x.SchoolId);
Property(x => x.SchoolId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(x => x.Name).IsRequired().IsUnicode(true).HasMaxLength(200);
HasMany(x => x.EntitiesOfSchool).WithRequired(x => x.PrimarySchool).HasForeignKey(person => person.SchoolId);
}
}
public sealed class PersonMap : EntityTypeConfiguration<Person>
{
public PersonMap()
{
ToTable("Persons");
HasKey(x => x.PersonId);
Property(x => x.PersonId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(x => x.Name).IsRequired().IsUnicode(true).HasMaxLength(256);
Map<Teacher>(configuration => configuration.Requires("PersonType").HasValue(1));
Map<Student>(configuration => configuration.Requires("PersonType").HasValue(2));
}
}
public sealed class TeacherMap : EntityTypeConfiguration<Teacher>
{
public TeacherMap()
{
HasMany(x => x.Buildings).WithRequired(x => x.AssignedGuardian).HasForeignKey(x => x.GuardianId);
}
}
public sealed class StudentMap : EntityTypeConfiguration<Student>
{
public StudentMap()
{
HasMany(x => x.BooksOnLoan).WithOptional(x => x.AssignedTo).HasForeignKey(x => x.AssignedToId);
}
}
UniversityDbContext.cs
public sealed class UniversityDbContext : DbContext
{
public UniversityDbContext() : base("Name=default")
{
this.Configuration.LazyLoadingEnabled = false; // disable lazy loading
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new SchoolMap());
modelBuilder.Configurations.Add(new PersonMap());
modelBuilder.Configurations.Add(new TeacherMap());
modelBuilder.Configurations.Add(new StudentMap());
}
public DbSet<School> Schools { get; set; }
}
表DDE的SQL代码和data.sql的种子
CREATE TABLE [dbo].[Schools](
[SchoolId] [int] IDENTITY(1,1) NOT NULL,
[Name] Nvarchar (200) not null
CONSTRAINT [PK_Schools] PRIMARY KEY CLUSTERED
(
[SchoolId] ASC
)) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Persons](
[PersonId] [int] IDENTITY(1,1) NOT NULL,
[SchoolId] [int] not null,
[PersonType] [int] not null,
[Name] nvarchar(256) not null
CONSTRAINT [PK_Persons] PRIMARY KEY CLUSTERED
(
[PersonId] ASC
)) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Buildings](
[BuildingId] [int] IDENTITY(1,1) NOT NULL,
[Name] nvarchar(200) not null,
[GuardianId] [int] not null,
CONSTRAINT [PK_Buildings] PRIMARY KEY CLUSTERED
(
[BuildingId] ASC
)) ON [PRIMARY]
GO
CREATE TABLE [dbo].[CourseBooks](
[CourseBookId] [int] IDENTITY(1,1) NOT NULL,
[BookNumber] varchar(200) not null,
[AssignedToId] [int] null,
CONSTRAINT [PK_CourseBooks] PRIMARY KEY CLUSTERED
(
[CourseBookId] ASC
)) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Persons] WITH CHECK ADD CONSTRAINT [FK_Schools_Persons] FOREIGN KEY([SchoolId])
REFERENCES [dbo].[Schools] ([SchoolId])
ALTER TABLE [dbo].[Buildings] WITH CHECK ADD CONSTRAINT [FK_Persons_Buildings] FOREIGN KEY([GuardianId])
REFERENCES [dbo].[Persons] ([PersonId])
ALTER TABLE [dbo].[CourseBooks] WITH CHECK ADD CONSTRAINT [FK_Persons_CourseBooks] FOREIGN KEY([AssignedToId])
REFERENCES [dbo].[Persons] ([PersonId])
INSERT INTO Schools (Name) values (N'Business'), (N'Education')
INSERT INTO Persons (Name, PersonType, SchoolId) values ('Eddy',1, 1), ('Fran',1, 1), ('Joe',2, 1), ('Kim',2, 1)
INSERT INTO Buildings (Name, GuardianId) values (N'Offsite staff', 1), (N'Main Business Building', 1)
INSERT INTO CourseBooks(AssignedToId, BookNumber) values (3, 'Course A book 1'),(3, 'Course C book 31')