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

本文关键字:ALL 连接 UNION 嵌套 代码 疯狂 EF4 | 更新日期: 2023-09-27 18:06:17

我有一个类,在它的'默认get方法'中包含了相当多的内容,像这样:

_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…

这是一个很长的SQL -我试着把它粘贴到gmail中给朋友发邮件,但是gmail (chrome浏览器)拖了我的后腿。不用说,我不会把它全部粘贴在这里,只是给你一个简单的错误。

开头是这样的:

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(6 !)个关卡中。

当我查看内部嵌套(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',我想升级,但这样做打破了很多东西-我的配置不工作,因为很多已经改变了它似乎。如果能解决这个疯狂的嵌套问题,我会通过升级重写整个东西,但我不知道它会怎么做?

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

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

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