如何对object类型/转换后的列进行过滤查询?
如何对object类型/转换后的列进行过滤查询?
嘿,我之前在项目里刚好处理过类似的sql_variant列(对应EF里的object?类型)过滤需求,咱们来一步步搞定它!
先确认下你给出的实体和数据库配置信息:
实体类定义
public partial class Measurement { public int Measurements_PK { get; set; } public object? Value { get; set; } public String Name_UQ { get; set; } public string DataType { get; set; } = null!; }
SQL列定义
[Value] [sql_variant] NULL
EF ModelBuilder配置
entity.Property(e => e.Value).HasColumnType("sql_variant");
接下来分享几种靠谱的过滤方式:
方法1:结合DataType列+显式类型转换(首推,因为你已经有记录类型的列了)
你的实体里刚好有DataType列,它明确记录了Value的实际存储类型,咱们可以先通过这个列缩小范围,再把Value转成对应类型后过滤,既安全又高效。
比如要找Value是整数100的记录,用LINQ的写法:
var targetInt = 100; var matchingMeasurements = dbContext.Measurements .Where(m => m.DataType == "int" && Convert.ToInt32(m.Value) == targetInt) .ToList();
如果遇到EF Core没办法把Convert.ToInt32正确转成SQL的CAST操作的情况,直接用原生SQL更稳妥:
var targetInt = 100; var matchingMeasurements = dbContext.Measurements .FromSqlRaw(@" SELECT * FROM Measurement WHERE DataType = {0} AND CAST([Value] AS int) = {1}", "int", targetInt) .ToList();
要是你要过滤字符串类型的Value,比如找包含"room_temp"的记录:
var keyword = "room_temp"; var matchingMeasurements = dbContext.Measurements .Where(m => m.DataType == "nvarchar" && Convert.ToString(m.Value)!.Contains(keyword)) .ToList();
方法2:利用SQL Server的SQL_VARIANT_PROPERTY函数(不用依赖自己的DataType列)
如果你的DataType列偶尔会有不准确的情况,或者不想额外维护它,SQL Server给sql_variant类型提供了SQL_VARIANT_PROPERTY函数,可以直接从列里获取实际存储的基础类型:
SELECT * FROM Measurement WHERE SQL_VARIANT_PROPERTY([Value], 'BaseType') = 'int' AND CAST([Value] AS int) = 100;
对应的EF Core写法就是用FromSqlRaw执行上面的原生SQL就行。
必须注意的坑!
- 千万不要跳过类型校验直接转
Value!比如你直接把所有Value转成int,要是其中有存储的是字符串,SQL会直接报错,必须先通过DataType列或者SQL_VARIANT_PROPERTY过滤出对应类型的记录再转换。 - 避免客户端求值!如果你写的LINQ表达式EF Core没办法转成SQL,它会把整个表的数据拉到本地再过滤,数据量大的时候性能会崩掉,所以复杂的转换优先用原生SQL或者确认LINQ能正确生成SQL。
- 索引问题:因为用了
CAST或者函数,普通的索引会失效,要是这个表数据量很大,建议建计算列(比如CAST([Value] AS int)作为计算列)然后给计算列加索引。
内容来源于stack exchange
相关产品推荐
相关产品推荐

