.NET Core 7 EF Core执行SQL报错:无法将string转为System.FormattableString
解决EF Core中
cannot convert from 'string' to 'System.FormattableString'错误 错误原因解析
你的代码存在三个核心问题:
- 参数类型不匹配:混合使用
$字符串插值与+字符串拼接,最终生成普通string类型,但Database.ExecuteSql要求传入FormattableString类型(用于参数化查询),触发类型转换错误。 - API使用错误:
ExecuteSql是执行增删改这类非查询语句的方法,返回值为受影响行数(int类型),无法直接返回查询结果的List<ApplicationDto>集合。 - SQL注入风险:直接拼接参数到SQL语句中,存在严重安全漏洞。
修复方案
使用EF Core的FromSqlInterpolated或FromSqlRaw方法执行参数化查询,同时确保查询结果正确映射到ApplicationDto。
方案1:使用FromSqlInterpolated(推荐,简洁安全)
该方法支持参数化插值字符串,自动处理参数绑定,避免SQL注入:
public List<ApplicationDto> ListOfApplications(ApplicationsFilterDto emp) { // 修正SQL中Criticality的列映射错误(原代码误用d.DetailsName,应使用d2.DetailsName) var appList = _context.Set<ApplicationDto>() .FromSqlInterpolated($@" select ApplicationsData.ApplicationID as ApplicationId, Application_Name as ApplicationName, CommonName, d.DetailsName as TypeOfApplication, AccessType, d2.DetailsName as Criticality, o.OwnerName as ApplicationOwner, DRRequired, se.[DB_Name] as [DataBase] from ApplicationsData left join [dbo].[Details] d with(nolock) on d.ID=ApplicationsData.ApplicationType and d.HeaderId=6 left join [dbo].[Details] d2 with(nolock) on d2.ID=ApplicationsData.Criticality and d2.HeaderId=7 left join dbo.[Owner] o with(nolock) on o.ApplicationId=ApplicationsData.ApplicationID left join dbo.[DataBase] se with(nolock) on se.ServerID=ApplicationsData.ServerId where ApplicationsData.ServerId={emp.serverID} OR SE.[DBID]={emp.databaseId} OR o.OwnerId={emp.ownerId}") .ToList(); return appList; }
方案2:使用FromSqlRaw配合SqlParameter(显式参数绑定)
如果需要更明确地控制参数,可使用SqlParameter:
public List<ApplicationDto> ListOfApplications(ApplicationsFilterDto emp) { var serverParam = new SqlParameter("@ServerId", emp.serverID); var databaseParam = new SqlParameter("@DatabaseId", emp.databaseId); var ownerParam = new SqlParameter("@OwnerId", emp.ownerId); var appList = _context.Set<ApplicationDto>() .FromSqlRaw(@" select ApplicationsData.ApplicationID as ApplicationId, Application_Name as ApplicationName, CommonName, d.DetailsName as TypeOfApplication, AccessType, d2.DetailsName as Criticality, o.OwnerName as ApplicationOwner, DRRequired, se.[DB_Name] as [DataBase] from ApplicationsData left join [dbo].[Details] d with(nolock) on d.ID=ApplicationsData.ApplicationType and d.HeaderId=6 left join [dbo].[Details] d2 with(nolock) on d2.ID=ApplicationsData.Criticality and d2.HeaderId=7 left join dbo.[Owner] o with(nolock) on o.ApplicationId=ApplicationsData.ApplicationID left join dbo.[DataBase] se with(nolock) on se.ServerID=ApplicationsData.ServerId where ApplicationsData.ServerId=@ServerId OR SE.[DBID]=@DatabaseId OR o.OwnerId=@OwnerId", serverParam, databaseParam, ownerParam) .ToList(); return appList; }
额外配置:注册无键实体
如果ApplicationDto不是EF Core实体(无对应数据库表),需在DbContext的OnModelCreating方法中配置为无键实体:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<ApplicationDto>().HasNoKey(); }
关键注意点
- 必须使用参数化查询,禁止直接拼接参数到SQL语句,杜绝SQL注入风险。
- 确保SQL查询列名与
ApplicationDto属性名完全匹配(大小写不敏感,但名称需一致)。 - 修正原SQL中
Criticality列的映射错误,避免返回错误数据。
内容的提问来源于stack exchange,提问作者ahmed abdelaziz
相关产品推荐
相关产品推荐

