SelectListItem 投影的 EFCore SqlException 对值和文本使用相同的 属性

EFCore SqlException for SelectListItem projection using same property for Value and Text

我创建了一个 SelectListHelper 来将我所有的下拉数据填充放在一个中心位置。它将我数据库中的行投影到 IEnumerable<SelectListItem> 的集合中,我的视图可以使用这些集合。这是 class:

的一部分
public class SelectListHelper
{
    private AppDbContext _db;

    public SelectListHelper(AppDbContext db)
    {
        _db = db;
    }

    public IEnumerable<SelectListItem> GetCountries(bool showAll = false)
    {
        return _db.Set<Country>().Where(x => showAll || x.Enabled == true).OrderBy(x => x.Name).Select(x => new SelectListItem { Value = x.Abbreviation, Text = x.Name }).ToList();
    }

    public IEnumerable<SelectListItem> GetGoogleCategories(bool showAll = false)
    {
        return _db.Set<GoogleCategory>().Where(x => showAll || x.Enabled == true).OrderBy(x => x.Name).Select(x => new SelectListItem { Value = x.Name, Text = x.Name }).ToList();
    }
}

GetCountries 以及为简洁起见而省略的所有其他函数都可以正常工作。他们使用不同的列投影到 SelectListItem.

ValueText 属性上

GetGoogleCategoriesName 列投影到 SelectListItemValueText 属性上。这会产生以下 SqlException:

An exception of type 'System.Data.SqlClient.SqlException' occurred in Microsoft.EntityFrameworkCore.dll but was not handled in user code Invalid column name 'Value'.

当我查看 GetCountries 函数生成的 SQL 时,它看起来像我预期的那样:

SELECT [x].[Abbreviation] AS [Value], [x].[Name] AS [Text]
FROM [Countries] AS [x]
WHERE [x].[Enabled] = 1
ORDER BY [Text]

然而,GetGoogleCategories 函数生成的 SQL 与我预期的不同:

SELECT [x].[Name] AS [Text]
FROM [GoogleCategories] AS [x]
WHERE [x].Enabled] = 1
ORDER BY [Value]

我在 Visual Studio 2017 (15.7.3) 中使用 EfCore 2.1.0。任何想法可能会发生什么?我可以通过返回名称数组并手动构建 SelectListItems 列表来解决此问题,但这让我担心我的数据访问层中的其他内容可能无法正常工作。


public class GoogleCategory
{
    [Key]
    public int Id { get; set; }

    [Required, StringLength(250)]
    public string Name { get; set; }

    public bool Enabled { get; set; } = true;
}

public class Country
{
    [Key]
    public int Id { get; set; }

    [Required, StringLength(250)]
    public string Name { get; set; }

    [Required, StringLength(2)]
    public string Abbreviation { get; set; }

    public bool Enabled { get; set; } = true;
}

这是 #12180: Invalid column name: orderby uses a column alias that does not exist 跟踪的 2.1 回归错误。

针对您的特定情况的解决方法是使用带参数的 SelectListItem 构造函数(2.1 中引入的功能):

return _db.Set<GoogleCategory>()
    .Where(x => showAll || x.Enabled == true)
    .OrderBy(x => x.Name)
    .Select(x => new SelectListItem(x.Name, x.Name) })
    .ToList();

当然,问题仍然存在。