EF Core 6:如何实现返回关联数据的非DbSet绑定控制器?
你遇到的问题核心是OData无法识别未注册的非实体类型UserInfo,同时类的属性访问权限不足导致序列化失败。以下是具体的解决步骤:
解决方案
1. 修正实体类的访问权限
首先确保所有实体类的属性是public,否则EF Core和OData无法正确读取、序列化属性值:
public class AccountInfo { public string id { get; set; } public string name { get; set; } public string email { get; set; } } public class ExtraInfo { public string id { get; set; } public string proxy { get; set; } } public class UserInfo { public AccountInfo account { get; set; } public ExtraInfo extra { get; set; } }
2. 配置OData模型,注册UserInfo类型
因为UserInfo没有对应的数据库表,OData默认不会自动识别它,需要在OData模型构建时显式注册:
using Microsoft.OData.ModelBuilder; // 在Program.cs或Startup.cs的服务配置中添加OData模型配置 var modelBuilder = new ODataConventionModelBuilder(); // 注册数据库中存在的实体表 modelBuilder.EntitySet<AccountInfo>("AccountInfo"); modelBuilder.EntitySet<ExtraInfo>("ExtraInfo"); // 将UserInfo注册为复杂类型(无需主键) modelBuilder.ComplexType<UserInfo>(); // 如果需要将UserInfo当作独立实体处理(比如支持单条查询),可以指定主键: // modelBuilder.EntityType<UserInfo>().HasKey(u => u.account.id); // 注册UserInfo对应的控制器路由 modelBuilder.EntitySet<UserInfo>("UserInfo"); // 配置OData服务 services.AddControllers().AddOData(options => { options.Select().Filter().OrderBy().Expand().Count().SetMaxTop(100); options.AddRouteComponents("odata", modelBuilder.GetEdmModel()); });
3. 创建独立的UserInfoController(推荐)
为了逻辑清晰,建议创建专门的控制器处理UserInfo的查询,替代原有的ExtraInfoController复用逻辑:
public class UserInfoController : ODataController { private readonly MyDbContext _context; private readonly ILogger<UserInfoController> _logger; public UserInfoController(MyDbContext context, ILogger<UserInfoController> logger) { _context = context; _logger = logger; } [EnableQuery(PageSize = 15)] public IQueryable<UserInfo> Get() { // 用Join优化关联查询,避免笛卡尔积性能问题 var query = from a in _context.AccountInfo join x in _context.ExtraInfo on a.id equals x.id select new UserInfo { account = a, extra = x }; return query; } }
4. 适配Blazor端需求
如果Blazor原有逻辑需要IQueryable<ExtraInfo>,可以在控制器中保留原有接口,新增UserInfo查询接口:
// 在ExtraInfoController中保留原有接口 [EnableQuery(PageSize = 15)] public IQueryable<ExtraInfo> Get() { return _context.ExtraInfo; }
内容的提问来源于stack exchange,提问作者Razzupaltuff
相关产品推荐
相关产品推荐

