C# 为什么LINQtoSQL有时允许我使用函数进行项目,但有时却不允许?

C# 为什么LINQtoSQL有时允许我使用函数进行项目,但有时却不允许?,c#,linq-to-sql,C#,Linq To Sql,这真让我困惑。我知道LINQtoSQL通过处理表达式树并尝试通过生成的查询转换内容来进行选择,这就是为什么有些函数转换不起作用的原因(这是一个常见的麻烦) 我在代码中遇到了这样一种情况,LINQ to SQL能够通过选择投影调用我的助手函数。。。有时候。事实上,当方法有一个名称时,它就可以工作,但如果它有另一个名称,它就不能工作。我认为下面的程序最好地说明了这一点(这是我能做的最简单的程序): 这是一个L2S错误。这是预期的工作 在反编译的源代码中,我发现: private static

这真让我困惑。我知道LINQtoSQL通过处理表达式树并尝试通过生成的查询转换内容来进行选择,这就是为什么有些函数转换不起作用的原因(这是一个常见的麻烦)

我在代码中遇到了这样一种情况,LINQ to SQL能够通过选择投影调用我的助手函数。。。有时候。事实上,当方法有一个名称时,它就可以工作,但如果它有另一个名称,它就不能工作。我认为下面的程序最好地说明了这一点(这是我能做的最简单的程序):


这是一个L2S错误。这是预期的工作

在反编译的源代码中,我发现:

    private static MethodSupport GetDecimalMethodSupport(SqlMethodCall mc)
    {
        if (mc.Method.IsStatic)
        {
            if (mc.Arguments.Count == 2)
            {
                string str;
                if (((str = mc.Method.Name) != null) && ((((str == "Multiply") || (str == "Divide")) || ((str == "Subtract") || (str == "Add"))) || ((str == "Remainder") || (str == "Round"))))
                {
                    return MethodSupport.Method;
                }
            }
            else if (mc.Arguments.Count == 1)
            {
                string str2;
                if (((str2 = mc.Method.Name) != null) && (((str2 == "Negate") || (str2 == "Floor")) || ((str2 == "Truncate") || (str2 == "Round"))))
                {
                    return MethodSupport.Method;
                }
                if (mc.Method.Name.StartsWith("To", StringComparison.Ordinal))
                {
                    return MethodSupport.Method;
                }
            }
        }
        return MethodSupport.None;
    }
搜索
“到”

嗯。。。还有一个地方。也许L2S认为你的值类型是小数。尝试添加第二个参数以中断
mc.Arguments.Count==1
条件


无论如何,这是一个错误。这背后没有更深层次的原因。通常情况下,L2S可以在最终选择中执行功能。这是EF仍然缺乏的一个很棒的特性


将其搁置,并尽快迁移到EF。L2S已被放弃。

ToValueType是唯一不起作用的字符串吗?如果你说的是真的,我谨慎地假设,这将是一个L2S错误(一个非常不寻常的错误)。通常,L2S可以在最终选择中执行函数。这是EF仍然缺乏的一个非常棒的特性。即使在LINQPad中,我也能够重现您描述的行为,每次您使用以
开始的方法到
(区分大小写)时,它都会抛出一个异常。感谢您提供的信息-我感觉这与它如何解释表达式树中的方法名称有关。更改参数计数或更改为实例方法似乎确实可以解决程序问题(尽管计划只重命名该方法并留下好的注释)。此外,它看起来并不像假定我的类型是双精度的,它通过一组
GetXMethodSupport
函数运行,但是
GetDecimalMethodSupport
应该同时检查
IsStatic
mc.Method.DeclaringType==typeof(decimal)
——这就是其他辅助方法所做的。是的,这就解释了。它认为这是一种“支持方法”。请考虑对用户语音项目进行投票,该项目要求打开源L2S,这样可以容易地修复这样的错误:
using System;
using Sandbox.Data;
using System.Linq;

namespace Sandbox.Console
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var dataContext = new SandboxDataContext())
            {
                try
                {
                    var myValueList = dataContext.Numbers.Select(x => new MyValue
                    {
                        Type = DoIt(x.Value),
                    }).ToList();

                    System.Console.WriteLine("DoIt Succeeded, found {0} results", myValueList.Count);
                }
                catch (NotSupportedException)
                {
                    System.Console.WriteLine("DoIt Failed, oh noes!");
                }

                try
                {
                    var myValueList = dataContext.Numbers.Select(x => new MyValue
                    {
                        Type = ToValueType(x.Value),
                    }).ToList();

                    System.Console.WriteLine("ToValueType Succeeded, found {0} results", myValueList.Count);
                }
                catch (NotSupportedException)
                {
                    System.Console.WriteLine("ToValueType Failed, oh noes!");
                }

                System.Console.ReadKey();
            }
        }

        public static MyValueType DoIt(int value)
        {
            return MyValueType.SpecialType;
        }

        public static MyValueType ToValueType(int value)
        {
            return MyValueType.SpecialType;
        }

        public sealed class MyValue
        {
            public MyValueType Type { get; set; }
        }

        public enum MyValueType
        {
            SpecialType,
        }
    }
}
    private static MethodSupport GetDecimalMethodSupport(SqlMethodCall mc)
    {
        if (mc.Method.IsStatic)
        {
            if (mc.Arguments.Count == 2)
            {
                string str;
                if (((str = mc.Method.Name) != null) && ((((str == "Multiply") || (str == "Divide")) || ((str == "Subtract") || (str == "Add"))) || ((str == "Remainder") || (str == "Round"))))
                {
                    return MethodSupport.Method;
                }
            }
            else if (mc.Arguments.Count == 1)
            {
                string str2;
                if (((str2 = mc.Method.Name) != null) && (((str2 == "Negate") || (str2 == "Floor")) || ((str2 == "Truncate") || (str2 == "Round"))))
                {
                    return MethodSupport.Method;
                }
                if (mc.Method.Name.StartsWith("To", StringComparison.Ordinal))
                {
                    return MethodSupport.Method;
                }
            }
        }
        return MethodSupport.None;
    }
if (mc.Method.Name.StartsWith("To", StringComparison.Ordinal))