[英]EF4 code-first - insanely nested UNION ALL and duplicated joins?
我的“默認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生成...
它是一個loooooooong 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(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現在看起來更好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.