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”,我想升级,但这样做打破了很多东西 - 我的配置不起作用,因为很多东西似乎已经改变。如果解决了这个疯狂的嵌套问题,我会通过升级来重写整个东西,但是我不知道它会如何呢?
好吧,所以我决定不从一个基地继承,而是实现一个接口与我的基地具有相同的属性。这让我打破DRY,因为我需要重新实现所有实体上的所有相同属性。我可以在配置上保留继承,所以它并不全是坏的。
生成的SQL现在看起来更好。
显示用户实体的整个映射,并提及是否有任何涉及的继承。 –
好吧,我想我现在全部了:) –
所有的实体都是从'BaseEntity'派生的吗?只是为了测试,试着去除这个继承。 EF可能认为你的映射是一个可以解释这些工会的大TPC继承结构。 –