Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为tinyint列生成的查询将强制转换为int_C#_Sql Server_Entity Framework - Fatal编程技术网

C# 为tinyint列生成的查询将强制转换为int

C# 为tinyint列生成的查询将强制转换为int,c#,sql-server,entity-framework,C#,Sql Server,Entity Framework,我正在查询一个tinyint列,entity framework生成一个SELECT查询,该查询为该列引入转换为INT,即使我在WHERE子句中使用的值是byte类型 查看模型,我的tinyint列生成的类型是byte 查看代码: byte byteValue = 6; var entityList = from r in rep.DataContext.FooTable where r.TinyintColumn == byteValue

我正在查询一个tinyint列,entity framework生成一个SELECT查询,该查询为该列引入转换为INT,即使我在WHERE子句中使用的值是byte类型

查看模型,我的tinyint列生成的类型是byte

查看代码:

byte byteValue = 6;
var entityList = from r in rep.DataContext.FooTable
                 where r.TinyintColumn == byteValue
                 select r;
查看生成的查询:

SELECT [Extent1].[TinyintColumn] AS [TinyintColumn] WHERE @p__linq__0 = CAST( [Extent1].[TinyintColumn] AS int) 
我在表演上有严格的限制,所以我不想在任何选择中使用这些角色

所以我的问题是,有什么办法可以避免这件事?还是我做错了什么


提前感谢。

强制转换将影响性能,因为索引不会用于
TinyintColumn

这是中第2点和第4点的组合。CAST是一个列上的函数,如果没有它,数据类型将不匹配

@p\uu linq\uu 0
应为tinyint或显式强制转换

然而,根据and(SO),LINQ可能不喜欢tinyint主键


你可以“字节”这个项目符号(对不起)并使用smallint…

我正在发布我针对这个问题采取的解决方案


EntityFramework4.0似乎总是生成带有强制转换tinyint或smallint字段的查询。因此,为了优化性能,我决定将这些字段改为INT,以避免强制转换,并将其他nvarchar字段的大小从nvarchar(50)改为nvarchar(30)。因此,最后我将行的大小从143字节更改为135字节。

我的同事在Entity Framework 4.0上发现了非常好的解决方法。
为smallint工作,我没有试过tinyint

代替equals(=)-使用Contains()运算符,该运算符是用EF 4.0实现的

例如:
假设您拥有SmallIntColumn列。

而不是:

short shortValue = 6;
var entityList = from r in rep.DataContext.FooTable
                 where r.SmallIntColumn == shortValue
                 select r;
short shortValue = 6;
var entityList = from r in rep.DataContext.FooTable
                 where r.SmallIntColumn == shortValue
                 select r;
使用

检查生成的SQL-现在没有强制转换
从我的测试来看,执行计划在列上使用了我的(过滤的)索引,非常完美

希望有帮助。

Shlomi

如果Sql表列数据类型为tinyint,则相应的POCO对象应具有byte类型的属性。这对你有用。否则,当您遍历LINQ对象时,它将抛出一个错误,指出无法将字节类型转换为int或您为属性定义的任何类型

我刚刚用EF 4.3代码优先的方法进行了验证,一切都很顺利。

如果使用IList.Contains列表,实体框架将不会强制转换

List<byte> byteValue = new List<byte> { 6 };
var entityList = from r in rep.DataContext.FooTable
             where byteValue.Contains(r.TinyintColumn)
             select r;
List byteValue=新列表{6};
var entityList=来自rep.DataContext.FooTable中的r
其中byteValue.Contains(r.TinyintColumn)
选择r;

我遇到了相同的问题。

我在使用带有lambda表达式的EF时遇到了完全相同的问题。将数据类型增强为int不是解决方案,甚至是不好的做法。我发现,正如其他人在这里报告的那样,当您采取更笨拙的方法时,您确实得到了正确的代码,例如:

SomeEntity.FindBy(i=>newlist{1}.Contains(i.TinyintColumn))

但当你遇到其他问题时,你会遇到不止一个要匹配的值。下面将不使用参数化的查询值,而只是将它们内联到查询体中

SomeEntity.FindBy(i=>newlist{1,2}.Contains(i.TinyintColumn))

这在最初的问题上并没有那么糟糕,但仍然不好,因为这意味着数据库必须为您向它抛出的每个值组合编写一个计划,并且由于没有适当的执行时间聚合,性能分析几乎是不可能的。它还有一些在高负载环境中看不到的性能影响

不要让我开始讨论这些行为/反模式对char/nchar数据类型的影响以及它们对索引的影响。在我看来,围绕数据类型系统C#implements集中所有内容既有局限性,也会导致重大问题

我对EF的看法是,对建模良好的表的非常基本的查询被转换为糟糕的SQL代码,EF遵循反模式。鉴于EF开发带来的炒作和增加的复杂性,我认为这不是一件令人印象深刻的事情!我现在不会在这里讨论这个问题,因为那将是一个完全不同的讨论


选择以上任何一种解决方案,但在使用它们之前要知道它们的缺点。也许EF的第10版会在一定程度上解决这个问题,但是我不会屏住呼吸。

如果你想保留你可以使用的逻辑。 代码如下 其中(e=>e.Id==i.FixIntCast()
并保持应用程序逻辑不变。

尝试更复杂的IntCastFixExtension版本:

namespace System.Linq {


/// <summary>
/// author: Filip Sielimowicz inspired by
/// http://www.entityframework.info/Home/SmallIntProblem
/// </summary>
public static class IntCastFixExtension {

    public static IQueryable<T> FixIntCast<T>(this IQueryable<T> q, bool narrowMemberExpr = true, bool narrowConstantExpr = true) {
        var visitor = new FixIntCastVisitor() {
            narrowConstExpr = narrowConstantExpr,
            narrowMembExpr = narrowMemberExpr
        };
        Expression original = q.Expression;
        var expr = visitor.Visit(original);
        return q.Provider.CreateQuery<T>(expr);
    }

    private class FixIntCastVisitor : ExpressionVisitor {

        public bool narrowConstExpr;
        public bool narrowMembExpr;

        protected override Expression VisitBinary(BinaryExpression node) {
            bool eq = node.NodeType == ExpressionType.Equal;
            bool neq = node.NodeType == ExpressionType.NotEqual;
            if (eq || neq) {
                var leftUncasted = ReducePossiblyNotNecessaryIntCastExpr(node.Left);
                var rightUncasted = ReducePossiblyNotNecessaryIntCastExpr(node.Right);
                var rightConst = node.Right as ConstantExpression;
                if (leftUncasted == null) {
                    return base.VisitBinary(node);
                }
                if (rightUncasted != null) {
                    if (NarrowTypesAreCompatible(leftUncasted.Type, rightUncasted.Type)) {
                        // Usuwamy niepotrzebne casty do intów występujące po obu stronach equalsa
                        return eq ? Expression.Equal(leftUncasted, rightUncasted) : Expression.NotEqual(leftUncasted, rightUncasted);
                    }
                } else if (rightConst != null) {
                    // Zamiast casta argumentu z lewej w górę do inta (tak zrobił linq2entity)
                    // zawężamy występującą po prawej stałą typu 'int' do typu argumentu z lewej
                    if (narrowConstExpr && (rightConst.Type == typeof(int) || rightConst.Type == typeof(int?))) {
                        var value = rightConst.Value;
                        var narrowedValue = value == null ? null : Convert.ChangeType(rightConst.Value, leftUncasted.Type);
                        Expression narrowedConstExpr = Expression.Constant(narrowedValue, leftUncasted.Type);
                        return eq ? Expression.Equal(leftUncasted, narrowedConstExpr) : Expression.NotEqual(leftUncasted, narrowedConstExpr);
                    }
                } else if (node.Right.NodeType == ExpressionType.MemberAccess) {
                    // Jak po prawej mamy wyrażenie odwołujące się do zmiennej typu int to robimy podobnie jak przy stałej
                    // - zawężamy to, zamiast upcasta do inta z lewej.
                    if (narrowMembExpr) {
                        var rightMember = node.Right;
                        var narrowedMemberExpr = Expression.Convert(rightMember, leftUncasted.Type);
                        return eq ? Expression.Equal(leftUncasted, narrowedMemberExpr) : Expression.NotEqual(leftUncasted, narrowedMemberExpr);
                    }
                }
            }
            return base.VisitBinary(node);
        }

        private bool NarrowTypesAreCompatible(Type t1, Type t2) {
            if (t1 == typeof(short?)) t1 = typeof(short);
            if (t2 == typeof(short?)) t2 = typeof(short);
            if (t1 == typeof(byte?)) t1 = typeof(byte);
            if (t2 == typeof(byte?)) t2 = typeof(byte);
            return t1 == t2;
        }

        private bool IsNullable(Type t) {
            return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>);
        }

        private Expression CorrectNullabilityToNewExpression(Expression originalExpr, Expression newExpr) {
            if (IsNullable(originalExpr.Type) == IsNullable(newExpr.Type)) {
                return newExpr;
            } else {
                if (IsNullable(originalExpr.Type)) {
                    Type nullableUncastedType = typeof(Nullable<>).MakeGenericType(newExpr.Type);
                    return Expression.Convert(newExpr, nullableUncastedType);
                } else {
                    Type notNullableUncastedType = Nullable.GetUnderlyingType(newExpr.Type);
                    return Expression.Convert(newExpr, notNullableUncastedType);
                }

            }
        }

        private Expression ReducePossiblyNotNecessaryIntCastExpr(Expression expr) {
            var unnecessaryCast = expr as UnaryExpression;
            if (unnecessaryCast == null ||
                unnecessaryCast.NodeType != ExpressionType.Convert ||
                !(unnecessaryCast.Type == typeof(int) || unnecessaryCast.Type == typeof(int?))
            ) {
                // To nie jest cast na inta, do widzenia
                return null;
            }
            if (
                (unnecessaryCast.Operand.Type == typeof(short) || unnecessaryCast.Operand.Type == typeof(byte)
                || unnecessaryCast.Operand.Type == typeof(short?) || unnecessaryCast.Operand.Type == typeof(byte?))
            ) {
                // Jest cast z shorta na inta
                return CorrectNullabilityToNewExpression(unnecessaryCast, unnecessaryCast.Operand);
            } else {
                var innerUnnecessaryCast = unnecessaryCast.Operand as UnaryExpression;
                if (innerUnnecessaryCast == null ||
                    innerUnnecessaryCast.NodeType != ExpressionType.Convert ||
                    !(innerUnnecessaryCast.Type == typeof(int) || innerUnnecessaryCast.Type == typeof(int?))
                ) {
                    // To nie jest podwójny cast między intami (np. int na int?), do widzenia
                    return null;
                }
                if (
                    (innerUnnecessaryCast.Operand.Type == typeof(short) || innerUnnecessaryCast.Operand.Type == typeof(byte)
                    || innerUnnecessaryCast.Operand.Type == typeof(short?) || innerUnnecessaryCast.Operand.Type == typeof(byte?))
                ) {
                    // Mamy podwójny cast, gdzie w samym środku siedzi short
                    // Robimy skrócenie, żeby intów nie produkował zamiast short -> int -> int?
                    // powinno ostatecznie wychodzić short -> short czyli brak castowania w ogóle.
                    return CorrectNullabilityToNewExpression(unnecessaryCast, innerUnnecessaryCast.Operand);
                }
            }
            return null;
        }
    }
}
名称空间系统.Linq{
/// 
///作者:Filip Sielimowicz灵感来源于
/// http://www.entityframework.info/Home/SmallIntProblem
/// 
公共静态类IntCastFixExtension{
公共静态IQueryable FixIntCast(此IQueryable q,bool-窄带成员expr=true,bool-窄带成员expr=true){
var visitor=new FixIntCastVisitor(){
窄带常数expr=窄带常数expr,
窄带MemberExpr=窄带MemberExpr
};
原始表达式=q.表达式;
var expr=访客访问(原件);
返回q.Provider.CreateQuery(expr);
}
私有类FixIntCastVisitor:ExpressionVisitor{
公共图书馆;
公共图书馆;
受保护的重写表达式访问二进制(BinaryExpression节点){
bool eq=node.NodeType==ExpressionType.Equal;
bool neq=node.NodeType==ExpressionType.NotEqual;
if(eq | | neq){
var leftUncasted=reducePossiblynotnecessaryNTCastXPR(node.Left);
var rightUncasted=reducePossiblynotnecessaryNTCastXPR(node.Right);
var rightcont=节点。右侧为恒常表达式;
short shortValue = 6;
var entityList = from r in rep.DataContext.FooTable
                 where r.SmallIntColumn == shortValue
                 select r;
short shortValue = 6;
var entityList = from r in rep.DataContext.FooTable
                 where r.SmallIntColumn.Equals(shortValue)
                 select r;