我一直在思考这个问题。有一些类似的案例,但解决方案不适用于我的案例。
我有一个方法,返回字符串格式的过滤器查询。该方法有不同的数据类型的逻辑,设置正确的值,列名等。
string filterQuery = GetFilterQuery(params);
rows = rows.Where(filterQuery);
我的问题是数据库中有Nullable DateTime
,而代码端有String
表示。
我已经尝试了以下查询(String
表示目前可能是错误的):
"BirthDate.ToString() = \"16.2.2012 22:00:00\""
结果:* 类型“DateTime?”上的方法不可访问 *
"BirthDate.Value.ToString() = \"16.2.2012 22:00:00\""
结果:LINQ to Entities无法识别方法“System.String ToString()",因此无法将此方法转换为存储表达式。
"BirthDate == null ? 1=1 : (DateTime)BirthDate.ToString() = \"16.2.2012 22:00:00\""
结果:* 应为.“"或”(“”*
有解决这个问题的办法吗?
更新(添加了更多关于查询生成的源代码)
var filterQueries = query.GridFilteringOptions.filters
// remove filters that doesn't have all the required information
.Where(o => o.name != string.Empty && o.value != string.Empty && !string.IsNullOrEmpty(o.type))
// remove filters that are filtering other tables than current
.Where(o => o.table == tableName)
.Select(filter => filter.ResolveQuery()).ToList();
if (filterQuery.Any())
{
var filterQuery = string.Join(" And ", filterQueries);
rows = rows.Where(filterQuery);
}
这里有一个类Filter和与此上下文相关的方法
public string ResolveQuery()
{
if (type == "Int64")
{
return ResolveInteger();
}
else if(type == "String")
{
return ResolveString();
}
else if(type == "DateTime")
{
return ResolveDateTime();
}
else
{
return string.Empty;
}
}
private string ResolveDateTime()
{
DateTime result = new DateTime();
if (DateTime.TryParse(this.value, out result))
{
return string.Format("{0}.ToString() = \"{1}\"", this.name, result.ToUniversalTime());
}
return string.Empty;
}
private string ResolveString()
{
switch (@operator)
{
default:
return string.Format(@"{0}.StartsWith(""{1}"")", this.name, this.value);
}
}
private string ResolveInteger()
{
string tmp = this.name;
switch (@operator)
{
case -1:
return string.Empty;
case 0:
tmp += "<";
break;
case 1:
tmp += "=";
break;
case 2:
tmp += ">";
break;
default:
return string.Empty;
}
tmp += value;
return tmp;
}
4条答案
按热度按时间m0rkklqb1#
LINQ to Entities无法识别
ToString()
方法。在将结果字符串插入查询之前,您必须对其进行求值。要在你的问题中创建示例,你可以这样处理它:
"BirthDate == null ? 1=1 : (DateTime)BirthDate.ToString() = \"16.2.2012 22:00:00\""
可能不起作用,因为LINQ to EF无法识别三元运算符(? :
)**编辑:**我从你的评论中了解到
BirthDate
是你的表中的一列,而不是一个变量。在这种情况下,你可以检索所有的条目,将它们转换成一个列表,然后使用LINQ对对象应用过滤器,如下所示(尽管你必须相应地修改你的filterQuery
):**未测试:**可能会使用数据库的
CONVERT
函数:eimct9ow2#
我的问题是,我在数据库中有可为空的DateTime,而在代码端有String表示。
为什么?
更改代码端,分析字符串表示形式,并在LINQ查询中为它指定适当的对象。
“出生日期.ToString()=“2012年2月16日22:00:00””
坏-如果你必须做字符串操作,AWLWAYS使用InvariantCulture。这段代码很脆弱,在任何其他国家都会崩溃。
cbjzeqam3#
我目前用try/catch块来解决这个问题,这增加了一些开销和丑陋,我宁愿找到一个替代方案,但它确实工作得很稳定:
注:从输入变量(
rule.field
和rule.data
)接受这些字段是危险的,可能会导致(困难的)盲目SQL注入。可以根据值白名单检查第一个值(rule.field
),以防止出现这种情况。pod7payv4#
我知道我的回答有点晚,但对于每一个仍然在同一个案件中挣扎的人,你可以尝试这个解决方案
这样,无论出生日期是DateTime还是DateTime?,它都将工作。最好检查出生日期之前是否不为空
方法.ToString()适用于日期时间和可为空的日期时间