You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor QuickGrid无法识别类字段的问题排查与解决请求

问题:QuickGrid无法识别实体类中存在的字段“InboundOriginalFileName”?

我有多年C#、ASP.NET及WinForms开发经验,正在将旧WinForms应用迁移至.NET 9.0 + Blazor技术栈。已创建实体类EncounterValidationOutput、DbContext,并在Index.razor页面中添加QuickGrid组件。在配置QuickGrid的PropertyColumn时,出现错误:“InboundOriginalFileName does not exist in the current context”,但该字段确实存在于EncounterValidationOutput类中,且SQL查询返回的列表对象encounterValidationOutputs包含该字段数据。

相关代码

Index.razor

@page "/encountervalidationoutputs"
@using Microsoft.EntityFrameworkCore
@using Microsoft.EntityFrameworkCore.Infrastructure
@using Microsoft.AspNetCore.Components.QuickGrid
@using EncounterBlazorApp.Models
@using EncounterBlazorApp.Data
@implements IAsyncDisposable
@inject IDbContextFactory<EncounterBlazorAppContext> DbFactory

<PageTitle>Index</PageTitle>

<h1>Index</h1>

<p>
    <a href="encountervalidationoutputs/create">Create New</a>
</p>

<QuickGrid Class="table" Items="encounterValidationOutputs.AsQueryable()" TGridItem="EncounterValidationOutput">
    <PropertyColumn Property="InboundOriginalFileName" Title="InboundOriginalFileName" />
</QuickGrid>

@code {
    private List<EncounterValidationOutput> encounterValidationOutputs = new();
    private EncounterBlazorAppContext? context = null;

    protected override async Task OnInitializedAsync()
    {
        context = await DbFactory.CreateDbContextAsync(); 
        encounterValidationOutputs = await context.Set<EncounterValidationOutput>().FromSqlRaw(@" SELECT [Transaction_File_Name] AS InboundOriginalFileName FROM [mydatabase].[dbo].[repository]").ToListAsync();

        // Debugging output 
        Console.WriteLine($"Fetched {encounterValidationOutputs.Count} items."); 
        if (encounterValidationOutputs.Any()) 
        { 
            Console.WriteLine($"First item's InboundOriginalFileName: {encounterValidationOutputs.First().InboundOriginalFileName}"); 
        }
    }

    public async ValueTask DisposeAsync()
    {
        if (context != null)
        {
            await context.DisposeAsync();
        }
    }
}

EncounterBlazorAppContext.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using EncounterBlazorApp.Models;

namespace EncounterBlazorApp.Data
{
    public class EncounterBlazorAppContext : DbContext
    {
        public EncounterBlazorAppContext(DbContextOptions<EncounterBlazorAppContext> options) : base(options)
        { }

        public DbSet<EncounterValidationOutput> EncounterValidationOutputs => Set<EncounterValidationOutput>();

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            // Configure EncounterValidationOutput as a keyless entity
            modelBuilder.Entity<EncounterValidationOutput>().HasNoKey();
        }
    }
}

Program.cs

using EncounterBlazorApp.Components;
using EncounterBlazorApp.Data;
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

// Register IDbContextFactory for EncounterBlazorAppContext
builder.Services.AddDbContextFactory<EncounterBlazorAppContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("EncounterBlazorAppContext"), sqlOptions =>
    {
        sqlOptions.CommandTimeout(60); // Set your desired command timeout in seconds
    })
);

// Add other services
builder.Services.AddQuickGridEntityFrameworkAdapter();
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorComponents().AddInteractiveServerComponents();

var app = builder.Build();

// Configure the HTTP request pipeline
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
    app.UseHsts();
    app.UseMigrationsEndPoint();
}

app.UseHttpsRedirection();
app.UseAntiforgery();
app.MapStaticAssets();
app.MapRazorComponents<App>().AddInteractiveServerRenderMode();

app.Run();

原因分析与解决方法

核心原因

QuickGrid的PropertyColumn依赖编译期表达式树解析,当你传入List<T>.AsQueryable()时,注册的QuickGridEntityFrameworkAdapter会尝试将属性访问转换为SQL查询逻辑,但你的场景中:

  1. 数据已经通过ToListAsync()加载到本地内存,无需服务器端操作
  2. 自定义SQL映射的字段在EF Core的表达式树解析中无法被正确关联到实体属性
  3. 使用字符串形式的Property参数缺少编译期检查,容易引发上下文识别错误

解决步骤

1. 直接传入本地集合,放弃IQueryable

既然数据已经加载到本地List<T>,直接将集合传给QuickGrid即可,无需调用AsQueryable(),同时改用lambda表达式形式的Property参数获得编译期检查:

<QuickGrid Class="table" Items="encounterValidationOutputs" TGridItem="EncounterValidationOutput">
    <PropertyColumn Property="x => x.InboundOriginalFileName" Title="InboundOriginalFileName" />
</QuickGrid>

2. 确认实体类属性的可访问性

检查EncounterValidationOutput实体类,确保InboundOriginalFileName是公共可读可写属性:

namespace EncounterBlazorApp.Models
{
    public class EncounterValidationOutput
    {
        // 必须是公共属性,且包含getter/setter
        public string InboundOriginalFileName { get; set; } = string.Empty;
        // 其他属性...
    }
}

3. 清理编译缓存(可选)

如果问题仍存在,清理项目的bin/obj目录,重新生成解决方案,避免编译缓存导致的上下文识别异常。


内容的提问来源于stack exchange,提问作者boilers222

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 04:29:50