2015-11-19 6 views
5

मैं निम्न त्रुटिका मेल कई भाव पेड़

पैरामीटर 'पी' इकाइयों में उल्लिखित LINQ क्वेरी अभिव्यक्ति में बाध्य नहीं था हो रही है।

मैं इस समस्या (ParameterExpression का एक ही उदाहरण पेड़ में सभी भाव से किया जाना चाहिए) को समझते हैं और समाधान मैं ऑनलाइन लेकिन कोई भाग्य के साथ मिल गया है उपयोग करने के लिए प्रयास किया है।

यह मेरा विधि

private void SeedEntity<TEntity>(DatabaseContext context, ref TEntity entity, params Expression<Func<TEntity, object>>[] identifierExpressions) where TEntity : class 
{ 
    Expression<Func<TEntity, bool>> allExpresions = null; 

    var parameters = identifierExpressions.SelectMany(x => x.Parameters).GroupBy(x => x.Name).Select(p => p.First()).ToList(); 

    foreach (Expression<Func<TEntity, object>> identifierExpression in identifierExpressions) 
    { 
     Func<TEntity, object> vv = identifierExpression.Compile(); 
     object constant = vv(entity); 

     ConstantExpression constExp = Expression.Constant(constant, typeof(object)); 
     BinaryExpression equalExpression1 = Expression.Equal(identifierExpression.Body, constExp); 
     Expression<Func<TEntity, bool>> equalExpression2 = Expression.Lambda<Func<TEntity, bool>>(equalExpression1, parameters); 

     if (allExpresions == null) 
     { 
      allExpresions = equalExpression2; 
     } 
     else 
     { 
      BinaryExpression bin = Expression.And(allExpresions.Body, equalExpression2.Body); 
      allExpresions = Expression.Lambda<Func<TEntity, bool>>(bin, parameters); 
     } 
    } 

    TEntity existingEntity = null; 
    if (allExpresions != null) 
    { 
     existingEntity = context.Set<TEntity>().FirstOrDefault(allExpresions); 
    } 

    if (existingEntity == null) 
    { 
     context.Set<TEntity>().Add(entity); 
    } 
    else 
    { 
     entity = existingEntity; 
    } 
} 

यह संपत्तियों की एक संख्या के आधार पर एक इकाई के देखने के लिए एक अभिव्यक्ति उत्पन्न करता है।

यह एक अभिव्यक्ति के लिए ठीक काम करता है, त्रुटि केवल एकाधिक में गुजरने पर होती है।

इस तरह कहा जाता है: एक ConstantExpression

आप कर सकते हैं के साथ

context.Set<TEntity>().FirstOrDefault(p=>p.Name == e.Name && p.Age == e.Age); 

की जगह e.Name & & e.Age:

SeedEntity(context, ref e, p=> p.Name);//Works 
SeedEntity(context, ref e, p=> p.Name, p=> p.Age);//Fails 

यह निम्न प्रदर्शन मेरे लिए कुछ इसी तरह उत्पन्न करता है उपर्युक्त विधि में देखें, मैं सभी अद्वितीय पैरा को पकड़ता हूं और उन्हें parameters में संग्रहीत करता हूं पी, फिर पूरे वैरिएबल का उपयोग करें। यह शुरुआत है, लेकिन फिर मुझे में params सरणी के रूप में पारित पैरामीटर के उदाहरणों को प्रतिस्थापित करने की आवश्यकता है, यह वह जगह है जहां मैं असफल रहा हूं।

मैं भाव की गणना और पैरामीटर

में .Update() विधि गुजर का उपयोग मैं भी का उपयोग कर ExpressionVisitor

public class ExpressionSubstitute : ExpressionVisitor 
{ 
    public readonly Expression from, to; 
    public ExpressionSubstitute(Expression from, Expression to) 
    { 
     this.from = from; 
     this.to = to; 
    } 
    public override Expression Visit(Expression node) 
    { 
     if (node == from) return to; 
     return base.Visit(node); 
    } 
} 

public static class ExpressionSubstituteExtentions 
{ 
    public static Expression<Func<TEntity, TReturnType>> RewireLambdaExpression<TEntity, TReturnType>(Expression<Func<TEntity, TReturnType>> expression, ParameterExpression newLambdaParameter) 
    { 
     var newExp = new ExpressionSubstitute(expression.Parameters.Single(), newLambdaParameter).Visit(expression); 
     return (Expression<Func<TEntity, TReturnType>>)newExp; 
    } 
} 
+0

बस एक त्वरित विचार, क्या आपने दूसरे पैरामीटर के लिए एक अलग अक्षर का उपयोग करने का प्रयास किया है? (यानी पी => p.Name, f => f.Age) –

+0

इनपुट के लिए धन्यवाद, यह कभी काम नहीं करेगा, क्योंकि आपके पास केवल एक पैरामीटर है लेकिन आप दो में गुजर रहे हैं। यह लैम्ब्डा –

+2

के लिए आपूर्ति किए गए पैरामीटर की गलत संख्या फेंक देगा प्रश्नों के संयोजन के बजाय, उन्हें लगातार क्यों लागू नहीं करें? 'परिणाम =/* पूर्ण सेट * /; foreach (अभिव्यक्ति) {परिणाम = परिणाम। कहाँ (अभिव्यक्ति)} '? चूंकि ईएफ 'IQueryable' का उपयोग करता है, इसलिए फ्रेमवर्क आवश्यक होने तक निष्पादन को रोक देगा, फिर SQL के लिए एक ही क्वेरी में सभी भविष्यवाणियों को गठबंधन करें। – Basic

उत्तर

4

आप वास्तव में करीब हैं एक समाधान की कोशिश की कोशिश की है। मुझे आपके parameters चर का बिंदु नहीं दिखाई देता है। उन्हें नाम से समूहित करना एक गलती है। क्यों अभिव्यक्ति से पैरामीटर पास नहीं करते? फिर आवश्यक होने पर जाएं। आपका आगंतुक कोड ठीक है।

private static void SeedEntity<TEntity>(DbContext context, ref TEntity entity, params Expression<Func<TEntity, object>>[] identifierExpressions) 
     where TEntity : class 
    { 
     Expression<Func<TEntity, bool>> allExpresions = null; 

     foreach (Expression<Func<TEntity, object>> identifierExpression in identifierExpressions) 
     { 
      Func<TEntity, object> vv = identifierExpression.Compile(); 
      object constant = vv(entity); 

      ConstantExpression constExp = Expression.Constant(constant, typeof(object)); 
      BinaryExpression equalExpression1 = Expression.Equal(identifierExpression.Body, constExp); 
      Expression<Func<TEntity, bool>> equalExpression2 = Expression.Lambda<Func<TEntity, bool>>(equalExpression1, identifierExpression.Parameters); 

      if (allExpresions == null) 
      { 
       allExpresions = equalExpression2; 
      } 
      else 
      { 
       var visitor = new ExpressionSubstitute(allExpresions.Parameters[0], identifierExpression.Parameters[0]); 
       var modifiedAll = (Expression<Func<TEntity,bool>>)visitor.Visit(allExpresions); 
       BinaryExpression bin = Expression.And(modifiedAll.Body, equalExpression2.Body); 
       allExpresions = Expression.Lambda<Func<TEntity, bool>>(bin, identifierExpression.Parameters); 
      } 
     } 

     TEntity existingEntity = null; 
     if (allExpresions != null) 
     { 
      existingEntity = context.Set<TEntity>().FirstOrDefault(allExpresions); 
     } 

     if (existingEntity == null) 
     { 
      context.Set<TEntity>().Add(entity); 
     } 
     else 
     { 
      entity = existingEntity; 
     } 
    } 
+1

मैंने अद्वितीय अनुमतियों को पकड़ लिया और सोचते हुए कि मैं पैरामीटर को प्रतिस्थापित करके उस उदाहरण का पुन: उपयोग कर सकता हूं (उपर्युक्त उदाहरण में नहीं)। आप समाधान काम करते हैं, बहुत बहुत धन्यवाद। मैं देखता हूं कि अब मैं कहाँ गलत हो गया –

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