У меня есть класс с несколькими включениями в его «метод 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;
}
}
IЯ работаю против CTP 4 'v4.0.30319', и я хочу обновить, но это ломает много вещей - моя конфигурация не работает, так как многое изменилось, кажется.Я бы переписал весь материал путем обновления, если бы это решило эту безумную проблему с вложенностью, но я не понимаю, как это будет?