LINQ 查询失败,并显示可为空的变量 ormlite



我正在尝试使用ServiceStack Ormlite编写以下LINQ查询。

dbConn.Select<Product>(p => p.IsActive.HasValue && p.IsActive.Value)

在这里,产品是我的项目类,"IsActive"是该类中的可为空的布尔属性。当此行执行时,它总是抛出"无效操作异常"与消息

从作用域 " 引用的类型为 " 的变量 'p',但未定义

我尝试了以下不同的变体,但仍然相同的异常结果

dbConn.Select<Product>(p => p.IsActive.HasValue == true && p.IsActive.Value == true)
dbConn.Select<Product>(p => p.IsActive != null && p.IsActive.Value == true)

但如果我只是写

dbConn.Select<Product>(p => p.IsActive.HasValue)

然后它起作用了。

我很困惑问题出在哪里?这是服务堆栈问题吗?

我的答案可以使用服务堆栈或mlite处理诸如"value"和"HasValue"之类的可为空的值。而且日期时间也为空,如"createdate.value.Year"。你必须改变两个地方。

  1. 修改访问会员访问方式:

protected virtual object VisitMemberAccess(MemberExpression m)
        {
            if (m.Expression != null)
            {
                 if (m.Member.DeclaringType.IsNullableType())
                 {
                    if (m.Member.Name == nameof(Nullable<bool>.Value))
                        return Visit(m.Expression);
                    if (m.Member.Name == nameof(Nullable<bool>.HasValue))
                    {
                        var doesNotEqualNull = Expression.NotEqual(m.Expression, Expression.Constant(null));
                            return Visit(doesNotEqualNull); // Nullable<T>.HasValue is equivalent to "!= null"
                    }
                    throw new ArgumentException(string.Format("Expression '{0}' accesses unsupported property '{1}' of Nullable<T>", m, m.Member));
                }
                if (m.Member.DeclaringType == typeof(DateTime))
                {
                    var ExpressionInfo = m.Expression as MemberExpression;
                    if (ExpressionInfo.Member.DeclaringType.IsNullableType())
                    {
                        if (ExpressionInfo.Member.Name == nameof(Nullable<bool>.Value))
                        {
                            var modelType = (ExpressionInfo.Expression as MemberExpression).Expression.Type;
                            var tableDef = modelType.GetModelDefinition();
                            var columnName = (ExpressionInfo.Expression as MemberExpression).Member.Name;
                            var QuotedColumnName = GetQuotedColumnName(tableDef, columnName);
                            if (m.Member.Name == "Year")
                            {
                                return new PartialSqlString(string.Format("DATEPART(yyyy,{0})", QuotedColumnName));
                            }
                            if (m.Member.Name == "Month")
                                return new PartialSqlString(string.Format("DATEPART(mm,{0})", QuotedColumnName));
                        }                            
                        if (ExpressionInfo.Member.Name == nameof(Nullable<bool>.HasValue))
                        {
                            var doesNotEqualNull = Expression.NotEqual(ExpressionInfo.Expression, Expression.Constant(null));
                            return Visit(doesNotEqualNull); // Nullable<T>.HasValue is equivalent to "!= null"
                        }
                    }
                    else
                    {
                        var modelType = ExpressionInfo.Expression.Type;
                        var tableDef = modelType.GetModelDefinition();
                        var columnName = ExpressionInfo.Member.Name;
                        var QuotedColumnName = GetQuotedColumnName(tableDef, columnName);
                        if (m.Member.Name == "Year")
                            return new PartialSqlString(string.Format("DATEPART(yyyy,{0})", QuotedColumnName));
                        if (m.Member.Name == "Month")
                            return new PartialSqlString(string.Format("DATEPART(mm,{0})", QuotedColumnName));
                    }
                }
                if (m.Expression.NodeType == ExpressionType.Parameter || m.Expression.NodeType == ExpressionType.Convert)
                { 
                    var propertyInfo = (PropertyInfo)m.Member;
                    var modelType = m.Expression.Type;
                    if (m.Expression.NodeType == ExpressionType.Convert)
                    {
                        var unaryExpr = m.Expression as UnaryExpression;
                        if (unaryExpr != null)
                        {
                            modelType = unaryExpr.Operand.Type;
                        }
                    }
                    var tableDef = modelType.GetModelDefinition();
                    if (propertyInfo.PropertyType.IsEnum)
                        return new EnumMemberAccess(
                            GetQuotedColumnName(tableDef, m.Member.Name), propertyInfo.PropertyType);
                    return new PartialSqlString(GetQuotedColumnName(tableDef, m.Member.Name));
                }
            }
            var member = Expression.Convert(m, typeof(object));
            var lambda = Expression.Lambda<Func<object>>(member);
            var getter = lambda.Compile();
            return getter();
        }

  1. 修改访问拉姆达方法

protected virtual object VisitLambda(LambdaExpression lambda)
        {
            if (lambda.Body.NodeType == ExpressionType.MemberAccess && sep == " ")
            {
                MemberExpression m = lambda.Body as MemberExpression;
                if (m.Expression != null)
                {
                    string r = VisitMemberAccess(m).ToString();
                    if (m.Member.DeclaringType.IsNullableType())
                        return r;
                    return string.Format("{0}={1}", r, GetQuotedTrueValue());
                }
            }
            return Visit(lambda.Body);
        }

这是 Linq 的本质。为了达到您的需求,您需要使用两个关闭位置:

 dbConn.Where<Product>(p => p.IsActive.HasValue).Where(p=>p.Value==true);

相关内容

  • 没有找到相关文章

最新更新