2011-12-28 23 views
8

में पता चला था मैं त्रुटि मिलती है:एक चक्र एक LINQ अभिव्यक्ति अपवाद

एक चक्र एक LINQ अभिव्यक्ति में खोजा गया था।

private IEnumerable<int> FilterIdsByClient(IEnumerable<int> entityIds) 
{ 
    entityIds = 
     MyObjectContext.CreateObjectSet<TEntity>() 
      .Where(x => x.ClientId == _clientId) 
      .Where(x => entityIds.Contains(x.Id)) 
      .Select(x => x.Id); 

    return entityIds.ToList(); 
} 

हालांकि यह किसी भी अपवाद फेंक नहीं है और ठीक काम करता है:

ToList() में

निम्न कार्य करना चाहते हैं, जबकि

private IEnumerable<int> FilterIdsByClient(IEnumerable<int> entityIds) 
{ 
    entityIds = 
     MyObjectContext.CreateObjectSet<TEntity>() 
      .Where(x => x.ClientId == _clientId) 
      .Where(x => entityIds.Contains(x.Id)) 
      .Select(x => x.Id) 
      .ToList(); 

    return entityIds; 
} 

(इस कोर्स के एक सरलीकृत संस्करण है) ।

किसी के पास कोई सुराग है कि यह अजीब व्यवहार क्यों होता है?

संपादित करें:

at System.Data.Objects.ELinq.Funcletizer.FuncletizingVisitor.Visit(Expression exp) 
    at System.Data.Objects.ELinq.Funcletizer.Funcletize(Expression expression, Func`1& recompileRequired) 
    at System.Data.Objects.ELinq.Funcletizer.FuncletizingVisitor.InlineExpression(Expression exp) 
    at System.Data.Objects.ELinq.Funcletizer.FuncletizingVisitor.InlineObjectQuery(ObjectQuery inlineQuery, Type expressionType) 
    at System.Data.Objects.ELinq.Funcletizer.FuncletizingVisitor.InlineValue(Expression expression, Boolean recompileOnChange) 
    at System.Data.Objects.ELinq.Funcletizer.FuncletizingVisitor.Visit(Expression exp) 
    at System.Linq.Expressions.EntityExpressionVisitor.VisitExpressionList(ReadOnlyCollection`1 original) 
    at System.Linq.Expressions.EntityExpressionVisitor.VisitMethodCall(MethodCallExpression m) 
    at System.Linq.Expressions.EntityExpressionVisitor.Visit(Expression exp) 
    at System.Data.Objects.ELinq.Funcletizer.FuncletizingVisitor.Visit(Expression exp) 
    at System.Linq.Expressions.EntityExpressionVisitor.VisitLambda(LambdaExpression lambda) 
    at System.Linq.Expressions.EntityExpressionVisitor.Visit(Expression exp) 
    at System.Data.Objects.ELinq.Funcletizer.FuncletizingVisitor.Visit(Expression exp) 
    at System.Linq.Expressions.EntityExpressionVisitor.VisitUnary(UnaryExpression u) 
    at System.Linq.Expressions.EntityExpressionVisitor.Visit(Expression exp) 
    at System.Data.Objects.ELinq.Funcletizer.FuncletizingVisitor.Visit(Expression exp) 
    at System.Linq.Expressions.EntityExpressionVisitor.VisitExpressionList(ReadOnlyCollection`1 original) 
    at System.Linq.Expressions.EntityExpressionVisitor.VisitMethodCall(MethodCallExpression m) 
    at System.Linq.Expressions.EntityExpressionVisitor.Visit(Expression exp) 
    at System.Data.Objects.ELinq.Funcletizer.FuncletizingVisitor.Visit(Expression exp) 
    at System.Linq.Expressions.EntityExpressionVisitor.VisitExpressionList(ReadOnlyCollection`1 original) 
    at System.Linq.Expressions.EntityExpressionVisitor.VisitMethodCall(MethodCallExpression m) 
    at System.Linq.Expressions.EntityExpressionVisitor.Visit(Expression exp) 
    at System.Data.Objects.ELinq.Funcletizer.FuncletizingVisitor.Visit(Expression exp) 
    at System.Data.Objects.ELinq.Funcletizer.Funcletize(Expression expression, Func`1& recompileRequired) 
    at System.Data.Objects.ELinq.ExpressionConverter..ctor(Funcletizer funcletizer, Expression expression) 
    at System.Data.Objects.ELinq.ELinqQueryState.CreateExpressionConverter() 
    at System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption) 
    at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption) 
    at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() 
    at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) 
    at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) 
    at ...FilterIdsByClient... 

EDIT2::

नोट करना चाहिए कि इस मामले में, IEnumerable<int> entityIds एक ajax अनुरोध और नहीं एक प्रश्न से से आ रही एक सूची है

यह स्टैक ट्रेस है कहीं।

+0

आप 'MyObjectContext.CreateObjectSet ) में (' एक चर के लिए और फिर LINQ क्वेरी में उपयोग के संकल्प को परिणाम की कोशिश कर सकते हैं: नीचे टिप्पणी देखते हैं? – sll

+0

लेकिन यह डीबी से तालिका वापस कर देगा, है ना? और यह भी मदद कैसे करेगा? –

उत्तर

9

व्यवहार अजीब लगता है क्योंकि आप बंद अर्थ विज्ञान सही ढंग से विचार नहीं कर रहे हैं।

private IEnumerable<int> FilterIdsByClient(IEnumerable<int> entityIds) 
{ 
    // The variable entityIds points to whatever was passed in: A List, according to the edited question. 

    entityIds =         //this is an assignment, changing the referent of entityIds 
     MyObjectContext.CreateObjectSet<TEntity>() 
      .Where(x => x.ClientId == _clientId) 
      .Where(x => entityIds.Contains(x.Id)) //this lambda closes over the variable entityIds 
      .Select(x => x.Id); 

    // The query now has a reference to the *variable* entityIds, not to the object that entityIds pointed to originally. 
    // The value of entityIds has been changed; it now points to the query itself! 
    // The query is therefore operating on itself; this causes the "cycle detected" message. 
    // Because of delayed execution, the query is not executed until the next line of code: 

    return entityIds.ToList(); 
} 
+0

+1 मुझे यह बताने से बचने के लिए धन्यवाद। – Mzn

4

उत्तर LINQ क्वेरी को entityIds पर असाइन नहीं करना है। समाधान के लिए @ स्टू का उत्तर देखें।

+0

ध्यान दें कि इकाई आईडी एक सूची है और एक क्वेरी नहीं है। इसका पुन: लिखकर आपका क्या मतलब है? कैसे ? –

+0

@gil: वास्तव में, इकाई आईडी एक चर है। अपवाद-उठाने कोड उदाहरण में, .Toist() कॉल पर, उस चर को फिर से सौंप दिया गया है और क्वेरी को इंगित किया गया है, सूची में नहीं। – phoog

+0

आपके पहले उदाहरण में, यह एक सूची नहीं है, बल्कि एक LINQ क्वेरी है। यह है कि त्रुटि बताती है। हालांकि, दूसरे उदाहरण में, 'toList' का आउटपुट ** entityIds' ** को सौंपा गया है ** ** क्वेरी चलने के बाद, इसलिए 'entityIds'' null' होगा। इसे फिर से लिखने के बारे में: मैं इससे आपकी सहायता नहीं कर सका क्योंकि यह उस पर निर्भर करता है जिसे आप पूरा करने की कोशिश कर रहे हैं। –

6

आप अपने पैरामीटर को क्यों असाइन कर रहे हैं? क्यों नहीं

private IEnumerable<int> FilterIdsByClient(IEnumerable<int> entityIds) 
{ 
    return 
     MyObjectContext.CreateObjectSet<TEntity>() 
      .Where(x => x.ClientId == _clientId) 
      .Where(x => entityIds.Contains(x.Id)) 
      .Select(x => x.Id) 
      .ToList(); 
} 
+0

यह मेरा सवाल नहीं था। मुझे पता है कि मैं ऐसा कर सकता हूं और मैं मानता हूं कि यह बेहतर है लेकिन मैं जानना चाहता था कि यह व्यवहार क्यों होता है। –

+0

निश्चित रूप से, बस यह इंगित करना चाहता था कि आप जिस तरीके से कार्य करते हैं, वह परेशानी, अवधि के लिए पूछ रहा है। स्पष्टीकरण बहुत सरल है: आप एक गणक असाइन कर रहे हैं जो आपके द्वारा निर्दिष्ट किए जा रहे मूल मूल्य का उपयोग करता है जैसे फूग बताता है। – Stu

3

बेशक एक चक्र है। आप एंटर आईडी का उपयोग कर लिंक एक्सटेंशन विधि में कर रहे हैं और यह क्वेरी स्वयं ही बनाई जा रही है। inputted IEnumerable को संशोधित करने के बजाय, एक नई क्वेरी वापसी इस प्रकार है:

private IEnumerable<int> FilterIdsByClient(IEnumerable<int> entityIds) 
{ 
    var query = 
     MyObjectContext.CreateObjectSet<TEntity>() 
      .Where(x => x.ClientId == _clientId) 
      .Where(x => entityIds.Contains(x.Id)) 
      .Select(x => x.Id); 

    return query.ToList(); 
} 
+0

लेकिन इकाई आईडी सिर्फ एक सूची है। एक प्रश्न नहीं –

+1

@gil: असल में, इकाई आईडी एक * परिवर्तनीय * है। अपवाद-उठाने कोड उदाहरण में, 'टॉलीस्ट()' कॉल पर, उस चर * को फिर से सौंप दिया गया है * और क्वेरी को इंगित करता है, सूची में नहीं। – phoog

+0

@gil फूग का जवाब देखें। यदि आप समझते हैं कि लिंक अभिव्यक्तियों का उपयोग बंद होने वाले लैम्ब्स का उपयोग करते हैं और इसलिए इसमें जटिलताएं शामिल हैं तो आपको बहुत फायदा होगा। – Mzn

संबंधित मुद्दे