实体框架投影行为

sat*_*986 5 c# linq entity-framework

这里的第一篇文章非常简单.

我一直在研究在我正在开发的应用程序中简化一些复杂的查询,我在下面稍微讨论一下.

所以说我有这两个类:

域实体"EmailRecipient"(与EF代码优先使用,因此期望使用相同的列名生成SQL表).

public class EmailRecipient
{
    public Guid Id { get; set; }
    public string FriendlyName { get; set; }
    public string ExchangeName { get; set; }
    public string Surname { get; set; }
    public string Forename { get; set; }
    public string EmailAddress { get; set; }
    public string JobTitle { get; set; }

    public virtual List<SentEmail> SentEmails { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

和一个名为"EmailLite"的JSON序列化的简单类定义为

public class EmailLite
{
    public string EmailAddress { get; set; }
    public Guid Id { get; set; }
    public string FriendlyName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

在我的专业EF6(.1.3)DbContext中,我有一个名为EmailRecipients的DbSet.

所以自然地对EmailRecipients执行这个linq表达式

EmailRecipients.Select(x => new EmailLite
        {
            Id = x.Id,
            EmailAddress = x.EmailAddress,
            FriendlyName = x.FriendlyName
        });
Run Code Online (Sandbox Code Playgroud)

生成的SQL是

SELECT 
    1 AS [C1], 
    [Extent1].[Id] AS [Id], 
    [Extent1].[EmailAddress] AS [EmailAddress], 
    [Extent1].[FriendlyName] AS [FriendlyName]
    FROM [dbo].[EmailRecipients] AS [Extent1]
Run Code Online (Sandbox Code Playgroud)

那么为什么我这样做:

Func<EmailRecipient, EmailLite> projectionFunction = x => new EmailLite
        {
            Id = x.Id,
            EmailAddress = x.EmailAddress,
            FriendlyName = x.FriendlyName
        };

EmailRecipients.Select(projectionFunction);
Run Code Online (Sandbox Code Playgroud)

如何获得以下(完整)SQL生成:

SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[FriendlyName] AS [FriendlyName], 
    [Extent1].[ExchangeName] AS [ExchangeName], 
    [Extent1].[Surname] AS [Surname], 
    [Extent1].[Forename] AS [Forename], 
    [Extent1].[EmailAddress] AS [EmailAddress], 
    [Extent1].[JobTitle] AS [JobTitle], 
    [Extent1].[SubscribedOn] AS [SubscribedOn]
    FROM [dbo].[EmailRecipients] AS [Extent1]
Run Code Online (Sandbox Code Playgroud)

非常感激任何的帮助!

干杯,周六

Ale*_*rck 3

IQueryable<T>.Select()接受一个Expression<Func<T,TOut>>as 参数,您实际使用的函数IEnumerable<T>.Select()接受一个委托。因此,您告诉 EF,从那一刻起,您将使用IEnumerable而不是,IQueryable查询的其余部分将在内存中执行 => 您正在获取所有列。

EmailRecipients   <-- in memory from here on --> .Select(projectionFunction);
Run Code Online (Sandbox Code Playgroud)

你需要做的就是改变projectionFunction成一个表达式,它就会起作用:

Expression<Func<EmailRecipient, EmailLite>> projectionFunction = x => new EmailLite
{
    Id = x.Id,
    EmailAddress = x.EmailAddress,
    FriendlyName = x.FriendlyName
};
Run Code Online (Sandbox Code Playgroud)