实体框架6一对多与每个表的层次结构

时间:2014-07-09 21:39:36

标签: c# sql entity-framework entity-framework-6

首先是信息:

我有以下型号:

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();
  }
}

数据库结构: Database Structure

现在,先决条件表是每个层次结构表的表。这使得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 集合,它也将被延迟加载!

我真的在这个问题上摸不着头脑。

0 个答案:

没有答案