2016-01-04 18 views
5

Bu beni gerçekten şaşırtıyor. LINQ-to-SQL, ifade ağacını işleyerek ve oluşturulan sorgu aracılığıyla bir şeyler çevirmeye çalışarak seçimleri işlediğini biliyorum, bu nedenle bazı işlev çevirileri özelliği çalışmaz (string.IsNullOrWhitespace düzenli bir sıkıntıdır).Neden LINQ-to-SQL bazen bir işlevi kullanarak proje oluşturmama izin veriyor, ancak bazen yapmıyor?

Kodumda LINQ-to-SQL'in bir Select projeksiyonu ... aracılığıyla yardımcı işlevimi çağırabildiği bir duruma rastladım. Aslında, yöntem bir adı olduğunda çalışır, ancak başka bir adıyla birlikte çalışmıyor. Ben (bu ben bunu yapabilir gibi yaklaşık olarak basit) bu en iyi aşağıdaki program tarafından gösterilmektedir düşünüyorum:

// #define BREAK_THE_CODE 

using System; 
using Sandbox.Data; 
using System.Collections.Generic; 
using System.Linq; 

namespace Sandbox.Console 
{ 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      using (var dataContext = new SandboxDataContext()) 
      { 
       List<MyValue> myValueList; 

       try 
       { 
        myValueList = dataContext.Numbers.Select(x => new MyValue 
        { 
#if BREAK_THE_CODE 
         Type = ToValueType(x.Value), 
#else 
         Type = DoIt(x.Value), 
#endif 
        }).ToList(); 
       } 
       catch (NotSupportedException) 
       { 
        System.Console.WriteLine("Not supported, oh noes!"); 
        System.Console.ReadKey(); 
        return; 
       } 

       System.Console.WriteLine(myValueList.Count); 
       System.Console.ReadKey(); 
      } 
     } 

#if BREAK_THE_CODE 
     public static MyValueType ToValueType(int value) 
#else 
     public static MyValueType DoIt(int value) 
#endif 
     { 
      return MyValueType.One; 
     } 

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

     public enum MyValueType 
     { 
      One, 
      Two, 
      Unknown, 
     } 
    } 
} 

destek veritabanı sadece tek bir sütun [Value] INT NOT NULL ile [Number] adlı tek bir tablo vardır.

yazılı olarak

program benim için çalışıyor, ama üstündeki #define uncommenting yöntem görüşmesinin adını geçecektir ve ToList() yürütürken daha sonra program NotSupportedException atacağım.

Bir kalıbı belirlemeye çalışmak için birkaç farklı yöntem adını denedim, ancak yapamadım. Metodu, To ile başlayan herhangi bir şekilde adlandırılmış gibi görünüyorsa NotSupportedException'u atıyor, ancak başka bir adla çalışıyor gibi görünüyor. Bu hala tuhaf.

Birisi neler olduğunu açıklayabilir mi?

Burada #define geçişi olmayan başka bir örnek var, yalnızca her iki yöntemi de arkada yapıyor ve hala aynı sorunu görüyorum. Özellikle, DoIt çalışır, ancak ToValueType yapmaz.

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, 
     } 
    } 
} 
+0

ToValue Çalışmayan tek dizeyi mi? Eğer söyledikleriniz doğruysa ve bunu varsaymak için tedbirliyim, bu bir L2S hatasıdır (gerçekten sıra dışı olanı). – usr

+0

Normalde, L2S son Seçimde sadece iyi işlevler çalıştırabilir. Bu, EF'in hala eksik olduğu harika bir özellik. – usr

+0

LINQPad'de bile anlattığınız davranışı yeniden üretebildim, her bir "To" (büyük/küçük harf duyarlı) ile başlayan bir yöntemi kullandığınızda, bir istisna atar. –

cevap

4

Bu L2S hatasıdır. Bunun çalışması bekleniyor. bozulamaz kaynak kodunda

bulduğum:
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; 
    } 

"To" aranıyor:

if (mc.Method.Name.StartsWith("To", StringComparison.Ordinal)) 

Hm ... bir başka yer yoktur. Belki de L2S, değer tiplerinin ondalık olduğunu düşünüyor. mc.Arguments.Count == 1 koşulunu kırmak için ikinci bir argüman eklemeyi deneyin. Neyse, bu bir hatadır. Bunun arkasında daha derin bir sebep yok. Normalde, L2S son Seçimde sadece iyi işlevler çalıştırabilir. Bu, EF'in hala eksik olduğu harika bir özellik.

Bunu istirahat edip EF asap'a geçirin. L2S terk edildi.

+0

Bilgi için teşekkürler - İfade ağacında yöntem ismini nasıl yorumladığıyla ilgili bir his vardı.Argümanın sayısının değiştirilmesi veya bir örnek metoduna geçilmesi, programı çözmek için görünür (ancak, yöntemin yeniden adlandırılması ve iyi bir yorum bırakılmasına rağmen). – Anthony

+0

Ayrıca, benim türümün çift olduğu varsayılır gibi görünmüyor, bir grup GetXMethodSupport işlevini çalıştırıyor, ancak "GetDecimalMethodSupport" her ikisi de 'IsStatic' ve 'mc.Method.DeclaringType == typeof (ondalık) - diğer yardımcı yöntemler ne yapıyor. – Anthony

+0

Evet, bunu açıklıyor. Bir "destek yöntemi" olduğunu düşünüyor. Lütfen açık kaynak L2S için soran Kullanıcı Ses öğesi için oy kullanmayı düşünün, böylesi hatalar kolayca düzeltilebilir: https://visualstudio.uservoice.com/forums/121579-visual-studio-2015/suggestions/11277618-open-source -linq-için-SQL – usr

İlgili konular