连接SQL Server的OData服务调用Swagger GET接口报构造函数错误
问题根因
异常的直接触发原因是EF Core实体配置错误:你在ODataContext的OnModelCreating方法中,对Contact类的Mail属性(类型为string?,属于EF Core原生支持的标量类型)使用了OwnsOne()配置。OwnsOne()是用来配置自定义复杂值对象/拥有实体类型导航属性的方法,对string类型使用该配置后,EF Core会将string识别为独立的用户实体类型,尝试寻找可绑定的构造函数完成实例化,而string的所有内置构造函数参数都无法和实体属性匹配,最终抛出你看到的异常。
注意:90%以上的同类EF Core「string无可用构造函数」异常,都是错误对string类型属性使用了导航属性/拥有实体配置导致的
除此之外你的代码还存在几处会导致OData接口运行异常的配置问题,一并修复即可正常运行。
修复步骤
- 删除错误的拥有实体配置
打开ODataContext.cs,直接删除OnModelCreating方法中的modelBuilder.Entity<Contact>().OwnsOne(c => c.Mail);代码行。string是EF Core默认支持的映射类型,无需额外做拥有实体配置即可直接映射数据库字段。 - 修正实体类属性访问权限
打开Contact.cs,将Created、Updated两个属性的访问修饰符从默认私有改为公开,否则EF Core无法正常读写这两个字段:[Column("created")] public DateTime Created { get; set; } [Column("updated")] public DateTime Updated { get; set; } - 修正配置重复创建问题
打开Program.cs,删除你手动实例化ConfigurationBuilder生成configuration变量的代码,直接使用WebApplicationBuilder自带的配置实例即可,避免配置读取不一致:// 删除以下冗余代码 // IConfiguration configuration = new ConfigurationBuilder() // .AddJsonFile("appsettings.json", true, true) // .Build(); // 修改DbContext注册代码 builder.Services.AddDbContext<ODataContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("Database"))); - 补全OData基础配置
修改AddOData注册逻辑,添加EDM模型注册,否则OData路由、序列化会出现异常:// 先引入对应命名空间 using Microsoft.OData.ModelBuilder; builder.Services.AddControllers().AddOData(options => { options.Select().Filter().OrderBy().Expand().SetMaxTop(100); var edmBuilder = new ODataConventionModelBuilder(); edmBuilder.EntitySet<Contact>("Contacts"); options.AddRouteComponents("odata", edmBuilder.GetEdmModel()); }); - 修正控制器路由与特性配置
- 将按主键查询接口的路由从
[Route("key")]改为[Route("{key}")],否则路由无法匹配传入的主键参数 - 将
confirmMainEmail接口的路由从[Route("confirmMainEmail/key")]改为[Route("confirmMainEmail/{key}")],同时移除该接口上的[EnableQuery]特性——该特性用于对实体类型集合做查询解析,直接返回string类型时不需要该特性,否则会触发序列化错误 - 列表查询接口返回DbSet时建议加上AsNoTracking提升查询性能,代码调整为
return Ok(_dbContext.Contacts.AsNoTracking());
- 将按主键查询接口的路由从
- 修正连接字符串转义问题
检查appsettings.json中的连接字符串,反斜杠需要正确转义,LocalDB实例部分要写为(LocalDB)\\MSSQLLocalDB,同时把<PathToMdf>替换为你本地mdf文件的实际绝对路径,JSON中路径反斜杠需要双写转义。
验证方式
完成以上修改后重新编译启动项目,调用GET /odata/Contacts接口即可正常返回数据库中的联系人数据,不会再出现string构造函数绑定的异常。
内容的提问来源于stack exchange,提问作者Angel
相关产品推荐
相关产品推荐

