首先是信息:
我有以下型号:
public class Prerequisite : BaseModel
{
public string Contract { get; set; }
public bool Ignorable { get; set; }
public virtual ICollection<PrerequisiteParameter> PrerequisiteParameters { get; set; }
}
public class PrerequisiteParameter : BaseModel
{
public virtual Prerequisite Prerequisite { get; set; }
public string Key { get; set; }
public string Value { get; set; }
}
public class ProductPrerequisite : Prerequisite
{
public ProductVersionComponent ProductVersionComponent { get; set; }
}
public class ProductVersionComponent : BaseModel
{
public ICollection<ProductPrerequisite> ProductPrerequisites { get; set; }
}
我有以下配置类:
class PrerequisiteConfiguration : EntityTypeConfiguration<Prerequisite>
{
public PrerequisiteConfiguration()
{
this.Property(p => p.Contract).HasColumnName("Contract");
this.Property(p => p.Ignorable).HasColumnName("Ignorable");
this.HasMany<PrerequisiteParameter>(p => p.PrerequisiteParameters)
.WithRequired(pp => pp.Prerequisite)
.WillCascadeOnDelete();
}
}
class ProductPrerequisiteConfiguration : EntityTypeConfiguration<ProductPrerequisite>
{
public ProductPrerequisiteConfiguration()
{
this.HasRequired<ProductVersionComponent>(pp => pp.ProductVersionComponent).WithMany(pvc => pvc.ProductPrerequisites);
}
}
class PrerequisiteParameterConfiguration : EntityTypeConfiguration<PrerequisiteParameter>
{
public PrerequisiteParameterConfiguration()
{
}
}
class ProductVersionComponentConfiguration : EntityTypeConfiguration<ProductVersionComponent>
{
public ProductVersionComponentConfiguration()
{
this.HasMany<ProductPrerequisite>(pvc => pvc.ProductPrerequisites).WithRequired(pp => pp.ProductVersionComponent).WillCascadeOnDelete();
}
}
数据库结构:
现在,先决条件表是每个层次结构表的表。这使得ProductVersionComponent的Id可以为空。
我遇到以下问题:
Prerequisite prerequisite = context.Prerequisites.Include(p => p.PrerequisiteParameters).Where(p => p.Id == prerequisiteId).FirstOrDefault();
调用上面的代码将返回 prerequisiteId 的先决条件,但 prerequisite.PrerequisiteParameters 将始终为null。
我已经启动了Sql Profiler,可以看到它生成的查询:
exec sp_executesql N'SELECT
[Project2].[Id] AS [Id],
[Project2].[Discriminator] AS [Discriminator],
[Project2].[Contract] AS [Contract],
[Project2].[Ignorable] AS [Ignorable],
[Project2].[Created] AS [Created],
[Project2].[CreatedBy] AS [CreatedBy],
[Project2].[Modified] AS [Modified],
[Project2].[ModifiedBy] AS [ModifiedBy],
[Project2].[ProductVersionComponent_Id] AS [ProductVersionComponent_Id],
[Project2].[C1] AS [C1],
[Project2].[Id1] AS [Id1],
[Project2].[Prerequisite_Id] AS [Prerequisite_Id],
[Project2].[Key] AS [Key],
[Project2].[Value] AS [Value],
[Project2].[Created1] AS [Created1],
[Project2].[CreatedBy1] AS [CreatedBy1],
[Project2].[Modified1] AS [Modified1],
[Project2].[ModifiedBy1] AS [ModifiedBy1]
FROM ( SELECT
[Limit1].[Id] AS [Id],
[Limit1].[Contract] AS [Contract],
[Limit1].[Ignorable] AS [Ignorable],
[Limit1].[Created] AS [Created],
[Limit1].[CreatedBy] AS [CreatedBy],
[Limit1].[Modified] AS [Modified],
[Limit1].[ModifiedBy] AS [ModifiedBy],
[Limit1].[Discriminator] AS [Discriminator],
[Limit1].[ProductVersionComponent_Id] AS [ProductVersionComponent_Id],
[Extent2].[Id] AS [Id1],
[Extent2].[Prerequisite_Id] AS [Prerequisite_Id],
[Extent2].[Key] AS [Key],
[Extent2].[Value] AS [Value],
[Extent2].[Created] AS [Created1],
[Extent2].[CreatedBy] AS [CreatedBy1],
[Extent2].[Modified] AS [Modified1],
[Extent2].[ModifiedBy] AS [ModifiedBy1],
CASE WHEN ([Extent2].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
FROM (SELECT TOP (1)
[Extent1].[Id] AS [Id],
[Extent1].[Contract] AS [Contract],
[Extent1].[Ignorable] AS [Ignorable],
[Extent1].[Created] AS [Created],
[Extent1].[CreatedBy] AS [CreatedBy],
[Extent1].[Modified] AS [Modified],
[Extent1].[ModifiedBy] AS [ModifiedBy],
[Extent1].[Discriminator] AS [Discriminator],
[Extent1].[ProductVersionComponent_Id] AS [ProductVersionComponent_Id]
FROM [dbo].[Prerequisites] AS [Extent1]
WHERE ([Extent1].[Discriminator] IN (N''ProductPrerequisite'',N''Prerequisite'')) AND ([Extent1].[Id] = @p__linq__0) ) AS [Limit1]
LEFT OUTER JOIN [dbo].[PrerequisiteParameters] AS [Extent2] ON [Limit1].[Id] = [Extent2].[Prerequisite_Id]
) AS [Project2]
ORDER BY [Project2].[Id] ASC, [Project2].[C1] ASC',N'@p__linq__0 int',@p__linq__0=13
返回以下内容:
Id Discriminator Contract Ignorable Created CreatedBy Modified ModifiedBy ProductVersionComponent_Id C1 Id1 Key Value Created1 CreatedBy1 Modified1 ModifiedBy1 Prerequisite_Id 13 ProductPrerequisite INFRASTRUCTURE_PROCESSOR_COUNT 1 NULL NULL NULL NULL 1 1 1 MIN 2 NULL NULL NULL NULL 13
对我来说,这表明查询加载了它具有的先决条件和唯一参数。我尝试了不同的Id,当有多个参数绑定到一个先决条件时,我能够返回多行。
由于FK克制,这会使级联删除失败。当我尝试以下操作时失败:
context.Prerequisites.Remove(prerequisite);
它生成以下SQL:
exec sp_executesql N'DELETE [dbo].[Prerequisites]
WHERE (([Id] = @0) AND ([ProductVersionComponent_Id] = @1))',N'@0 int,@1 int',@0=13,@1=1
好像它没有将参数识别为儿童。
现在,如果我去创建一个 ProductPrerequisite ,给它提供属性并将 ProductVersionComponent 链接到它,并保存对象,它将用正确的数据填充数据库,钥匙!
ProductPrerequisite newPrereq = this.CreateProductPrerequisite(dbComponent, prerequisite);
context.Prerequisites.Add(newPrereq);
context.SaveChanges();
如果我加载 PrerequisiteParameter 导航到其先决条件属性,它将被正确延迟加载。如果我然后转到 PrerequisiteParameters 集合,它也将被延迟加载!
我真的在这个问题上摸不着头脑。