zoukankan      html  css  js  c++  java
  • C# 6.0 内插字符串 (Interpolated Strings )

    看Interpolated Strings之前,让我们先看EF Core 2.0 的一个新的特性:String interpolation in FromSql and ExecuteSqlCommand

    var city = "London";
    
    using (var context = CreateContext())
    {
        context.Customers
           .FromSql($@"
               SELECT *
               FROM Customers
               WHERE City = {city}")
           .ToArray();
    }
    

    SQL语句以参数化的方式执行,所以是防字符串注入的。

    @p0='London' (Size = 4000)
    
    SELECT *
    FROM Customers
    WHERE City = @p0
    

    一直认为Interpolated Strings只是String.Format的语法糖,传给FromSql的方法只是一个普通的字符串,已经移除了花括号,并把变量替换成了对应的值。FromSql获取不到变量信息,怎么实现参数化查询的呢? OK,让我们从头看起吧。

    什么是内插字符串 (Interpolated Strings)

    内插字符串是C# 6.0 引入的新的语法,它允许在字符串中插入表达式。

    var name = "world";
    Console.WriteLine($"hello {name}");
    

    这种方式相对与之前的string.Format或者string.Concat更容易书写,可读性更高。就这点,已经可以令大多数人满意了。事实上,它不仅仅是一个简单的字符串。

    内插字符串 (Interpolated Strings) 是什么?

    用代码来回答这个问题:

    var name = "world";
    string str1 = $"hello {name}";  //等于 var str1 = $"hello {name}";
    IFormattable str2 =  $"hello {name}";
    FormattableString str3 = $"hello {name}";
    

    可以看出,Interpolated Strings 可以隐式转换为3种形式。实际上式编译器默默的为我们做了转换:

    var name = "world";
    string str1 = string.Format("hello {0}",name);  //等于 var str1 = $"hello {name}";
    IFormattable str2 = FormattableStringFactory.Create("hello {0}",name);
    FormattableString str3 = FormattableStringFactory.Create("hello {0}",name);
    
    • IFormattable 从.net Framwork 1 时代就有了,只有一个ToString方法,可以传入IFormatProvider 来控制字符串的格式化。今天的主角不是他。
    • FormattableString 伴随Interpolated Strings引入的新类。

    FormattableString 是什么?

    先看一段代码

    var name = "world";
    FormattableString fmtString = $"hello {name}";
    Console.WriteLine(fmtString.ArgumentCount);  //1
    Console.WriteLine(fmtString.Format);  //hello {0}
    foreach (var arg in fmtString.GetArguments())
    {
        Console.WriteLine(arg);  //world
        Console.WriteLine(arg.GetType()); //System.String
    }
    

    可以看出FormattableString保存了Interpolated Strings的所有信息,所以EF Core 2.0能够以参数化的方式来执行SQL了。

    EF Core 中的注意事项

    因为隐式转换的原因,在使用EF Core的FromSql 方法和 ExecuteSqlCommand方法时,需要特别小心。一不留神就会调入陷阱。

    var city = "London";
    
    using (var context = CreateContext())
    {
        //方法一,非参数化
        var sql = $" SELECT * FROM Customers WHERE City = {city}";
        context.Customers.FromSql(sql).ToArray();
    
        //方法二,参数化
        context.Customers.FromSql($" SELECT * FROM Customers WHERE City = {city}").ToArray();
    
       //方法三,参数化
        FormattableString fsql = $" SELECT * FROM Customers WHERE City = {city}";
        context.Customers.FromSql(fsql).ToArray();
    
        //方法四,非参数化
        var sql = " SELECT * FROM Customers WHERE City = @p0";
        context.Customers.FromSql(sql, city).ToArray();
    
    }
    

    第一种方法,因为sql的赋值被编译成String.Format方法的调用,返回的是字符串。sql变量传入FromSql方法时,又经过一次System.StringMicrosoft.EntityFrameworkCore.RawSqlString隐式转换。但sql变量本身已经丢失了参数信息,所以无法实现参数化的查询。
    第四种方法, 也是Interpolated Strings -> String -> RawSqlString的转换过程,但因为变量是分开传入FromSql方法的,所以是以参数化的方式执行的。

    其他

    熟悉ES2015的同学可以看看Javascript中的实现,Tagged template literals,这和Interpolated Strings 非常类似。

    昨晚凌晨12点发帖,不知道为什么被移除首页了。感觉是篇幅不够的原因,重新加了点EF Core注意事项,但超过1小时没办法重新回首页了。七年来的第一篇文章,有点遗憾。希望大家喜欢。

  • 相关阅读:
    201521123088《JAVA程序设计》第8周学习总结
    201521123088《Java程序设计》第七周学习总结
    201521123088《Java程序设计》第6周学习总结
    201521123088《JAVA程序设计》第5周学习总结
    网络15软工个人作业5——软件工程总结
    alpha阶段个人总结
    软件工程网络15个人作业3--案例分析
    结对编程 201521123027
    软件工程网络15个人阅读作业2--提出问题(201521123027 陈龙)
    软件工程网络15个人阅读作业1(201521123027 陈龙)
  • 原文地址:https://www.cnblogs.com/csproj/p/Interpolated_Strings.html
Copyright © 2011-2022 走看看