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',我想升级,但这样做打破了很多东西-我的配置不工作,因为很多已经改变了它似乎。如果能解决这个疯狂的嵌套问题,我会通过升级重写整个东西,但我不知道它会怎么做?
好的,所以我决定不从基继承,而是实现一个具有与我的基相同属性的接口。这让我打破了DRY,因为我需要重新实现所有我的实体上的所有相同的属性。我可以在配置中保留继承,所以它并不全是坏的。
生成的SQL现在看起来更好。