EF4代码优先 - 疯狂嵌套UNION ALL和重复连接?

问题描述:

我有不少包括在它的“默认get方法”一类,像这样:EF4代码优先 - 疯狂嵌套UNION ALL和重复连接?

_dbContext.Users 
    .Include(c => c.PublicContact) 
    .Include(c => c.PrivateContact) 
    .Include(c => c.Product) 
    .Include(c => c.Languages) 
    .Include(c => c.Categories) 
    .Include(c => c.Memberships) 
    .Include(c => c.SearchWords) 
    .Include(c => c.Referals) 
    .Include(c => c.Files) 
    .Include(c => c.Articles); 

用户从BaseEntity继承,看起来像这样:

public class BaseEntity : IEntity 
{ 
    public BaseEntity() 
    { 
     DateTime createdTime = DateTime.Now; 
     Created = createdTime; 
     Modified = createdTime; 
    } 

    public int Id { get; set; } 
    public byte[] Timestamp { get; set; } 
    public DateTime Created { get; set; } 
    public DateTime Modified { get; set; } 
} 

当针对查询,试图找到一个特定的用户,它需要几秒钟(实际上几乎一分钟) - 所以我添加了一个探查器,差点跌倒椅子观察生成的实际SQL ...

它是一个loooooooong SQL - 我试图粘贴它到Gmail邮件一个朋友,但Gmail(铬)滞后了我。不用说,我不会在这里粘贴这一切,只是给你一个问题出在哪里。

它开始时是这样的:

DECLARE @p__linq__0 int = 1, 
     @p__linq__1 int = 153 

SELECT 
[UnionAll6].[C2] AS [C1], 
[UnionAll6].[C3] AS [C2], 
[UnionAll6].[C4] AS [C3], 
... 
[UnionAll6].[C121] AS [C121], 
[UnionAll6].[C122] AS [C122], 
[UnionAll6].[C123] AS [C123] 
FROM (SELECT 
     [UnionAll5].[C1] AS [C1], 
     [UnionAll5].[C2] AS [C2], 
     [UnionAll5].[C3] AS [C3], 

正如你所看到的,它从“UnionAll6”,这是因为它巢6这些疯狂的选择电平来选择(SIX!)。

当我查看内部嵌套(UnionAll1)时,我发现它实际上嵌套得更深 - 这次它从称为[Limit1],[Limit2]等的选择中选择了正确名称的字段,就像这个'[Limit1]。[EmailAddress] AS [EmailAddress]'。在这个层面上(连同选择Limit1.EmailAddress)我也觉得这样的:

CAST(NULL AS varchar(1)) AS [C2], 
CAST(NULL AS datetime2) AS [C3], 
CAST(NULL AS varchar(1)) AS [C4], 

所有这些选择实际上是嵌套再次从这个时候是这样的:

(SELECT TOP (1) 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Name] AS [Name], 
    [Extent1].[EmailAddress] AS [EmailAddress], 
    [Extent1].[LongDescription] AS [LongDescription], 
    [Extent1].[Modified] AS [Modified], 

这个水平似乎是最后一个,并且执行了一些沉重的左外部联接(实际上其中一些是针对额外的嵌套选择)。然后这是UNION ALL与其他一些废话,看起来很激动。

我有一些很多一对多的关系 - 他们是这样定义的配置:

public class UsersConfiguration : EntityBaseConfiguration<Users> 
{ 
    public UsersConfiguration() 
    { 
     HasMany(c => c.Languages).WithMany(); 
     HasMany(c => c.Categories).WithMany(); 
    } 
} 

public class EntityBaseConfiguration<T> : EntityConfiguration<T> where T : BaseEntity 
{ 
    public EntityBaseConfiguration() 
    { 
     HasKey(e => e.Id); 
     Property(e => e.Id).IsIdentity(); 
     Property(e => e.Timestamp).IsConcurrencyToken() 
      .IsRequired() 
      .HasStoreType("timestamp") 
      .StoreGeneratedPattern = StoreGeneratedPattern.Computed; 
     Property(e => e.Created) 
      .StoreGeneratedPattern = StoreGeneratedPattern.None; 
     Property(e => e.Modified) 
      .StoreGeneratedPattern = StoreGeneratedPattern.None; 
    } 
} 

我竞选对手的CTP 4“v4.0.30319”,我想升级,但这样做打破了很多东西 - 我的配置不起作用,因为很多东西似乎已经改变。如果解决了这个疯狂的嵌套问题,我会通过升级来重写整个东西,但是我不知道它会如何呢?

+0

显示用户实体的整个映射,并提及是否有任何涉及的继承。 –

+0

好吧,我想我现在全部了:) –

+0

所有的实体都是从'BaseEntity'派生的吗?只是为了测试,试着去除这个继承。 EF可能认为你的映射是一个可以解释这些工会的大TPC继承结构。 –

好吧,所以我决定不从一个基地继承,而是实现一个接口与我的基地具有相同的属性。这让我打破DRY,因为我需要重新实现所有实体上的所有相同属性。我可以在配置上保留继承,所以它并不全是坏的。

生成的SQL现在看起来更好。