2010-04-28 6 views
8

पर कोई समर्थित अनुवाद नहीं है मेरे पास कक्षा है, उपयोगकर्तालिंक से SQL DynamicInvoke (System.Object []) 'के पास SQL ​​

उपयोगकर्ता में उपयोगकर्ता आईडी संपत्ति है।

static IQueryable<User> FilterById(this IQueryable<User> p, Func<int, bool> sel) 
{ 
    return p.Where(m => sel(m.UserId)); 
} 

अपरिहार्य रूप से, जब मैं फ़ंक्शन को कॉल करें:

var users = Users.FilterById(m => m > 10); 

मैं निम्न अपवाद प्राप्त करें:

विधि

मैं एक विधि है कि कुछ इस तरह दिखता है 'System.Object डायनामिक इनवोक (System.Object [])' में एसक्यू के लिए समर्थित अनुवाद नहीं है एल

क्या इस समस्या का कोई समाधान है? अभिव्यक्ति के खरगोश छेद कितनी दूर है। KillMeAndMyFamily() मुझे जाना होगा?

क्यों स्पष्टीकरण मैं यह कर रहा हूं: मैं एक साधारण भंडार और पाइप की एक प्रणाली को स्वत: उत्पन्न करने के लिए टी 4 टेम्पलेट का उपयोग कर रहा हूं। पाइप, बजाय लेखन के भीतर: चलो एक उदाहरण के रूप UserId लेते हैं

new UserPipe() 
    .UserId(m => m > 10) 
    .UserName(m => m.Contains("oo")) 
    .LastName("Wee"); 
+6

अभिव्यक्ति के लिए +1.किल्म और MyFamily() – BenDundee

उत्तर

15

:

new UserPipe().Where(m => m.UserId > 10 && m.UserName.Contains("oo") && m.LastName == "Wee"); 

मैं की तरह कुछ उत्पन्न करने के लिए करना चाहते हैं।

new UserPipe().UserId(uid => uid > 10); 

और यह एक ही होने के लिए के रूप में चाहते हैं:

new UserPipe().Where(user => user.UserID > 10); 

आपको क्या करने की जरूरत है पहले संस्करण की अभिव्यक्ति पेड़ लेने के लिए और दूसरे संस्करण में अनुवाद करने के लिए है आप लिखना चाहते हैं ।


तो, पहले एक संकलित लैम्ब्डा के बजाय एक अभिव्यक्ति पेड़ को स्वीकार करने के UserId के हस्ताक्षर को बदलने: फिर

public static IQueryable<User> UserId(
    IQueryable<User> source, Expression<Func<int, bool>> predicate) 

, एक विधि है कि दूसरी करने के लिए पहली अभिव्यक्ति पेड़ धर्मान्तरित बारे में संस्करण।के दो अभिव्यक्ति के पेड़ पर एक नजर है:

इनपुट:

 
     Lambda 
     uid 
      | 
     BinaryOp 
      > 
    /   \ 
Parameter  Constant 
    uid   10 

आउटपुट:

 
     Lambda 
      user 
      | 
     BinaryOp 
      > 
    /   \ 
Property   Constant 
    UserID    10 
    | 
Parameter 
    user 

आप देख सकते हैं, तुम सब करने की जरूरत है शरीर ले लैम्ब्डा की, रिकर्सिवली पैरामीटर user पर संपत्ति UserId साथ पैरामीटर uid की सभी घटनाओं की जगह और एक नया भेड़ का बच्चा बनाने तब्दील शरीर और पैरामीटर user साथ दा अभिव्यक्ति।

आप एक ExpressionVisitor का उपयोग प्रतिस्थापन करने के लिए कर सकते हैं।

0

पहली नज़र में, यह आपको लगता है कि Linq पता करने के लिए T-SQL में अनुवाद करने के लिए कैसे नहीं जा रहा है कुछ भाव बना रहे हैं की तरह लग रहा है।

मैं गलत तरीके से समझ सकता हूं कि आप क्या करने का प्रयास कर रहे हैं, लेकिन यदि आप चेन-सक्षम अभिव्यक्तियां बनाना चाहते हैं जो लिंक से एसक्यूएल समझ सकते हैं, तो मैं अत्यधिक भविष्यवाणी बिल्डर एक्सटेंशन here पर विचार करने की अत्यधिक अनुशंसा करता हूं। यहां तक ​​कि अगर यह समझ है कि यह कैसे आप क्या कवर के तहत प्राप्त करने के लिए क्या आप काम कर रहे हैं बनाने की जरूरत है पर कुछ जानकारी दे सकता है काम करता है कि आप क्या चाहते वास्तव में नहीं है,। , अब

public class ExpressionMemberMerger : ExpressionVisitor 
{ 
    MemberExpression mem; 
    ParameterExpression paramToReplace; 

    public Expression Visit<TMember, TParamType>(
     Expression<Func<TParamType, bool>> exp, 
     Expression<Func<TMember, TParamType>> mem) 
    { 
     //get member expression 
     this.mem = (MemberExpression)mem.Body; 

     //get parameter in exp to replace 
     paramToReplace = exp.Parameters[0]; 

     //replace TParamType with TMember.Param 
     var newExpressionBody = Visit(exp.Body); 

     //create lambda 
     return Expression.Lambda(newExpressionBody, mem.Parameters[0]); 
    } 

    protected override Expression VisitParameter(ParameterExpression p) 
    { 
     if (p == paramToReplace) return mem; 
     else return base.VisitParameter(p); 
    } 
} 

मैं नीचे दिए गए कोड की तरह कुछ के साथ, विधेय, मुझे मालूम होता परिवर्तित कर सकते हैं: DTB को

1

धन्यवाद, यहाँ क्या मैं के साथ आया है। मैं इस कोड पर परीक्षण के वी बिट किया है; ऐसा लगता है कि, लेकिन मुझे कोई टिप्पणी/चिंताओं को सुनने में दिलचस्पी होगी:

static IQueryable<User> FilterById(this IQueryable<User> p, Expression<Func<int, bool>> sel) 
{ 
    var merger = new ExpressionMemberMerger(); 

    Expression<Func<User, int>> mem = m => m.UserId; 

    var expression = (Expression<Func<User, bool>>)merger.Visit(sel, mem); 

    return p.Where(expression); 
}