首页 > 解决方案 > EF Core 中的字符串 concat 和字符串插值之间有什么区别吗?

问题描述

我使用 asp.net core 2.1 和 EF Core 2。我曾调用 FromSql() 来使用原始查询。但是发生了一些奇怪的结果。

var finds = db.JournalInfos.FromSql<JournalInfo>($"SELECT * FROM `journalinfos` WHERE `journalinfos`.`Date` LIKE '{dateKey}%' ORDER BY `Index`").ToList();
var b = finds.Count(); //the count is 0 (It can't count noramlly)

var test = db.JournalInfos.FromSql<JournalInfo>("SELECT * FROM `journalinfos` WHERE `journalinfos`.`Date` LIKE '" + dateKey + "%' ORDER BY `Index`").ToList();
var a = test.Count(); //but in here, the count is normal (1054)

我认为 2 个 sql 字符串之间没有任何区别。

监视窗口显示2个sql字符串值的结果相同

我尝试更改这两个语句的顺序,以查看在同一实体上调用 FromSql 两次以上是否存在问题,但结果是相同的。一种使用字符串插值,另一种使用 + 连接字符串。

正如你在上面看到的,他们的 string.Equal() 结果也是一样的。(但使用字符串插值情况,它不会返回有效计数)但是如果我使用字符串变量来存储每个值并将其传递给每个 FromSql 参数,那么它们的查询结果是相同的。(有效的)

string sql1 = $"SELECT * FROM `journalinfos` WHERE `journalinfos`.`Date` LIKE '{dateKey}%' ORDER BY `Index`";
var finds = db.JournalInfos.FromSql<JournalInfo>(sql1).ToList();
var b = finds.Count(); //Now, it can count normally (1054)

string sql2 = "SELECT * FROM `journalinfos` WHERE `journalinfos`.`Date` LIKE '" + dateKey + "%' ORDER BY `Index`";
var test = db.JournalInfos.FromSql<JournalInfo>(sql2).ToList();
var a = test.Count(); //Also too. (1054)

c# 或 EF Core 中的字符串 + 连接和字符串插值之间有什么区别吗?

标签: asp.netentity-frameworkentity-framework-core

解决方案


内插字符串

内插字符串可以转换为 call String.Format()。当您将其存储在字符串变量中时会发生这种情况:

string sql1 = $"...";
var finds = db.JournalInfos.FromSql<JournalInfo>(sql1);

但是,如果您直接传递插值字符串(如屏幕截图中所示),它将FormattableString根据文档方法参数的类型:

var finds = db.JournalInfos.FromSql<JournalInfo>($"...");

在第二种情况下,数据库提供程序格式化您的查询并转义危险字符以避免 SQL 注入攻击。如果您想找出确切的区别,您必须在 EF Core 中启用敏感数据日志记录才能查看实际查询。

LINQ 方法

对于这个特定问题,可能有比使用原始 SQL 查询更简单的解决方案。LINQ 扩展方法被编译为 SQL,在 SQL 注入方面是安全的,并且如果您的数据库模型发生更改,则更容易维护。

DateTime date; // This is the same variable like in line 1603 on your screenshot

DateTime minInclusive = new DateTime(date.Year, date.Month, 1);
DateTime maxExclusive = minInclusive.AddMonths(1);

var finds = db.JournalInfos
    .Where(journal => journal.Date >= minInclusive && journal < maxExclusive)
    .OrderBy(journal => journal.Index)
    .ToList();

推荐阅读