【问题标题】:Why EF core tell me 'specified member is unmapped'?为什么 EF 核心告诉我“指定的成员未映射”?
【发布时间】:2021-02-22 08:39:56
【问题描述】:

我想按名称过滤用户并使用投影查询(通过 Select)返回一个新的 DTO:

var result = context.Users
    .Where(user => user.FullName == search)
    .Select(u => new UserPagingViewModel
    {
        Id = u.Id,
        IsSearchable = u.IsSearchable,
        FirstName = u.FirstName,
        LastName = u.LastName,
        FullName = u.FullName,
        Photo200 = u.Photo200,
        City = u.City,
        About = u.About,
        Skills = u.UserSkills.Select(us => us.Skill.Name),
        IsTeamMember = u.UserTeams.Any(ut => ut.UserAction == UserActionEnum.JoinedTeam)
    })
    .ToList();

用户类别:

public class User : IHasId
{
    public long Id { get; set; }
    public string FirstName { get; set; }
    public string SecondName { get; set; }
    public string LastName { get; set; }
    public string City { get; set; }
    public string About { get; set; }
    public string Telegram { get; set; }
    public string Email { get; set; }
    public string Mobile { get; set; }
    public string FullName => FirstName + " " + SecondName + " " + LastName;
    public string Photo100 { get; set; }
    public string Photo200 { get; set; }
    public bool IsModerator { get; set; }
    public List<UserTeam> UserTeams { get; set; }
    public List<UserSkill> UserSkills { get; set; }

    [NotMapped]
    public List<Team> TeamsToRecruit { get; set; }
    [NotMapped]
    public bool AnyTeamOwner { get; set; }
}

数据库是PostgreSql。数据提供者PostgreSQL/Npgsql provider for Entity Framework Core

但是当我尝试执行这个请求时,我得到了一个带有以下消息的异常:

LINQ 表达式 'DbSet() .Where(u => user.FullName == search)' 无法翻译。附加信息:实体类型“用户”上成员“全名”的翻译 失败的。这通常发生在指定成员未映射时。 要么以可翻译的形式重写查询,要么切换 通过插入对“AsEnumerable”的调用来明确地进行客户评估, “AsAsyncEnumerable”、“ToList”或“ToListAsync”。看 https://go.microsoft.com/fwlink/?linkid=2101038 了解更多信息。

我不想使用客户评估。 例如,如果我比较 FirstName 属性,一切正常。

请帮我弄清楚如何解决这个问题。

【问题讨论】:

  • FullName 未映射(可能还有其他事情),故事结束...要么将它们作为计算字段添加到您的数据库中,然后将其添加到您的模型构建器中,或者不要在查询中使用它
  • FullName 是一个计算出来的get 属性,不是数据库表本身的成员,这意味着它不能被转换为SQL 查询,因为该列可能不存在那里。将属性更改为具有getset,或者通过数据库表中确实存在的其他列进行查询。
  • 其实,与其走我建议的兔子洞,不如把这个// FullName = u.FullName,注释掉
  • @00110001,哦,表中确实没有列,结果一切都很简单:) 非常感谢!但是评论 // FullName = u.FullName 的选项不起作用,我真的不明白为什么它应该起作用

标签: c# .net asp.net-core entity-framework-core linq-to-entities


【解决方案1】:

您在三个地方都有 FullName。由于您没有全名列(或计算列),因此您不能在 dbcontext 查询中使用它。它将生成如下所示的 sql。

SELECT FULLNAME,... FROM USERS WHERE FULLNAME = N"some value".

这就是您收到错误的原因。

您需要从 dbcontext 查询中删除所有 FullName 并执行如下过滤器。

var result = context.Users
    .Where(x => (x.FirstName + " " + x.SecondName + " " + x.LastName) == search)
    .Select(u => new UserPagingViewModel
    {
        Id = u.Id,
        IsSearchable = u.IsSearchable,
        FirstName = u.FirstName,
        LastName = u.LastName,
        //FullName = u.FullName,
        Photo200 = u.Photo200,
        City = u.City,
        About = u.About,
        Skills = u.UserSkills.Select(us => us.Skill.Name),
        IsTeamMember = u.UserTeams.Any(ut => ut.UserAction == UserActionEnum.JoinedTeam)
    })
    .ToList();

这会让你像下面这样

FROM [Users] AS [t]
WHERE ([t].[FirstName] + N' ' + [t].[SecondName] + N' ' + [t].[LastName]) = N'some value' 

然后从 User 对象中删除 FullName。

public class User : IHasId
{
    public long Id { get; set; }
    public string FirstName { get; set; }
    public string SecondName { get; set; }
    public string LastName { get; set; }
    public string City { get; set; }
    public string About { get; set; }
    public string Telegram { get; set; }
    public string Email { get; set; }
    public string Mobile { get; set; }
    // public string FullName => FirstName + " " + SecondName + " " + LastName;
    public string Photo100 { get; set; }
    public string Photo200 { get; set; }
    public bool IsModerator { get; set; }
    public List<UserTeam> UserTeams { get; set; }
    public List<UserSkill> UserSkills { get; set; }

    [NotMapped]
    public List<Team> TeamsToRecruit { get; set; }
    [NotMapped]
    public bool AnyTeamOwner { get; set; }
}

将 FullName 添加到 UserPagingViewModel。

public class UserPagingViewModel{
    ...
    public string FirstName { get; set; }
    public string SecondName { get; set; }
    public string LastName { get; set; }
    public string FullName => $"{FirstName} {SecondName} {LastName}";
}

如果您希望 FullName 作为用户对象的一部分,则添加为未映射或使用 HasComputedColumnSql

【讨论】:

  • 是的,同样的错误,这个查询仍然尝试在 DB 端执行,并且没有 FullName 字段
  • 我想我忽略了你的问题,我更新了答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-07
  • 2017-06-30
  • 1970-01-01
相关资源
最近更新 更多