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

.NET Core 7 EF Core执行SQL报错:无法将string转为System.FormattableString

解决EF Core中cannot convert from 'string' to 'System.FormattableString'错误

错误原因解析

你的代码存在三个核心问题:

  1. 参数类型不匹配:混合使用$字符串插值与+字符串拼接,最终生成普通string类型,但Database.ExecuteSql要求传入FormattableString类型(用于参数化查询),触发类型转换错误。
  2. API使用错误:ExecuteSql是执行增删改这类非查询语句的方法,返回值为受影响行数(int类型),无法直接返回查询结果的List<ApplicationDto>集合。
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 05:14:57