2012-05-23 15 views
5

इकाइयों में linq में हमें एक विधि की आवश्यकता है जो "sql like" जैसा काम करता है। हम IQueryable के लिए अपने स्वयं के विस्तार विधि को लागू किया है, क्योंकि शामिल विधि हमारे लिए काम नहीं है, क्योंकि जैसे पैटर्न को स्वीकार नहीं करता '% एक% ख%'एक्सटेंशन विधि जहां लिनक में इकाइयों को

बनाई कोड है:

private const char WildcardCharacter = '%'; 

public static IQueryable<TSource> WhereLike<TSource>(this IQueryable<TSource> _source, Expression<Func<TSource, string>> _valueSelector, string _textSearch) 
{ 
    if (_valueSelector == null) 
    { 
     throw new ArgumentNullException("valueSelector"); 
    } 

     return _source.Where(BuildLikeExpressionWithWildcards(_valueSelector, _textSearch)); 
} 

private static Expression<Func<TSource, bool>> BuildLikeExpressionWithWildcards<TSource>(Expression<Func<TSource, string>> _valueSelector, string _textToSearch) 
{ 
    var method = GetPatIndexMethod(); 

    var body = Expression.Call(method, Expression.Constant(WildcardCharacter + _textToSearch + WildcardCharacter), _valueSelector.Body); 

    var parameter = _valueSelector.Parameters.Single(); 
    UnaryExpression expressionConvert = Expression.Convert(Expression.Constant(0), typeof(int?)); 
    return Expression.Lambda<Func<TSource, bool>> (Expression.GreaterThan(body, expressionConvert), parameter); 
} 

private static MethodInfo GetPatIndexMethod() 
{ 
    var methodName = "PatIndex"; 

    Type stringType = typeof(SqlFunctions); 
    return stringType.GetMethod(methodName); 
} 

यह ठीक से काम करता और कोड SqlServer में पूरी तरह से क्रियान्वित किया जाता है, लेकिन अब हम जहां खंड के रूप में अंदर इस विस्तार विधि का प्रयोग करेंगे:

myDBContext.MyObject.Where(o => o.Description.Like(patternToSearch) || o.Title.Like(patterToSerch)); 

समस्या यह है कि तरीकों जहां खंड में प्रयोग किया जाता है एक bool परिणाम वापस जाने के लिए अगर है इसका इस्तेमाल किया ऑपरेटरों के साथ '||' , और मुझे नहीं पता कि मेरे द्वारा बनाए गए कोड को एक बूल देता है और कोड को SQL सर्वर में निष्पादित किया जाता है। मुझे लगता है कि मुझे बॉल करने के लिए BuildLinqExpression विधि द्वारा लौटा हुआ अभिव्यक्ति परिवर्तित करना है, लेकिन मुझे नहीं पता कि यह कैसे करें

समेट करने के लिए! सबसे पहले लिंक से उन इकाइयों में अपनी खुद की विस्तारित विधियां बनाना संभव है जो SQL सर्वर में कोड निष्पादित करते हैं? अगर यह संभव है तो मुझे यह कैसे करना है?

आपकी मदद के लिए धन्यवाद।

+2

आप उपयोग कर [ 'SqlMethods.Like'] (http कोशिश किया। microsoft.com/en-us/library/system.data.linq.sqlclient.sqlmethods.like.aspx)? – dasblinkenlight

+0

@dasblinkenlight SqlMethods का उपयोग लिंक से एंटिटी में नहीं किया जा सकता है। –

उत्तर

3

नहीं, आप अपने कस्टम एक्सटेंशन विधियों को संसाधित करने के लिए ईएफ को शिक्षित नहीं कर सकते हैं, भले ही आपके पास ऐसे कोड हैं जो ईएफ के लिए उपयोग योग्य हों।

कोई एक:

  • अपने एफई Where अभिव्यक्ति में सीधे SqlFunctions तरीकों का उपयोग
  • एक ExpressionVisitor का उपयोग एक समग्र (OrElse/AndAlso) अभिव्यक्ति में कई भाव गठबंधन करने के लिए (ध्यान दें कि यह आप में मदद नहीं करेगा कोड जैसे आप चाहते हैं, लेकिन यह आपको अपने दो तरीकों का उपयोग करने और || पर प्रदर्शन करने देगा - हालांकि यह जटिल लगेगा, हालांकि

पहला सरल और स्पष्ट है।

+0

यदि मैं गलत नहीं हूं SqlMethods का उपयोग linq में इकाइयों में नहीं किया जा सकता है, मैंने कोशिश की है और मुझे क्रैश कर दिया है। एक अन्य उपयोगकर्ताओं ने वही रिपोर्ट की है http://stackoverflow.com/questions/2584598/linq-sqlmethods-like-fails –

+0

@Marc क्षमा करें, मुझे शायद 'एसक्यूएलफंक्शन' का अर्थ है - यानी वह कोड जो आप पहले से ही बोनेट –

+0

@Marc के तहत उपयोग कर रहे हैं और : यदि वह आपकी खुद की कक्षा है, तो: ऐसा कुछ भी नहीं है जो आप कर सकते हैं। हो सकता है कि बस एसक्यूएल लिखें और LINQ लिखने की कोशिश करने के बजाय * EF के माध्यम से * इसे दबाएं। –

2

यहाँ उत्तर दिया: https://stackoverflow.com/a/10726256/84206

उनकी कोड: http://pastebin.com/4fMjaCMV

आप [Expandable] के रूप में एक विस्तार विधि टैग करने के लिए और इतने लंबे समय अभिव्यक्ति के रूप में यह linq2entities साथ काम करता है देता है, यह आंतरिक के साथ अपने समारोह कॉल का स्थान ले लेगा की अनुमति देता है अभिव्यक्ति। ध्यान दें कि इनलाइन lambdas त्रुटियों दे, तो मैं उन्हें स्थानीय चर या इस तरह के IsCurrent चर यहाँ के रूप में स्थिर चर के रूप में घोषित करने के लिए किया था: // MSDN:

static Expression<Func<PropertyHistory, bool>> IsCurrent = (p) => p.Starts <= DateTime.Now; 

[ExpandableMethod] 
public static IQueryable<PropertyHistory> AsOf(this IQueryable<PropertyHistory> source) 
{ 
    return source.Where(IsCurrent); 
} 
संबंधित मुद्दे