question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Question] How to create where condition from dictionary of values?

See original GitHub issue

How to create where condition from dictionary of values? I have dictionary that contains values for where conditions

var pkkeys = new Dictionary<string, object>
{
     { "pkkey1", "value1"  },
     { "pkkey2", "value2"  }
}

I need to create something like this

db.GetTable<SomeTable>().Where(t => t.pkkey1 == "value1" && t.pkkey2 == "value2");

Thanks

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:25 (14 by maintainers)

github_iconTop GitHub Comments

5reactions
sdanylivcommented, Jun 5, 2018

@ifle, here we go. Extension methods:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using LinqToDB;
using LinqToDB.Expressions;
using LinqToDB.Linq;

namespace Linq2dbUtils
{
   public static class DynamicExtensions
   {
      private static readonly MethodInfo SetMethodInfo = MemberHelper
         .MethodOf<object>(o => ((IUpdatable<object>) null).Set(null, 0))
         .GetGenericMethodDefinition();

      private static readonly MethodInfo SqlPropertyMethodInfo = typeof(Sql).GetMethod("Property")
         .GetGenericMethodDefinition();

      public enum FieldSource
      {
         Propety,
         Column
      }

      public static Func<ParameterExpression, KeyValuePair<string, object>, Expression> GetFieldFunc(FieldSource fieldSource)
      {
         switch (fieldSource)
         {
            case FieldSource.Propety:
               return GetPropertyExpression;
            case FieldSource.Column:
               return GetColumnExpression;
            default:
               throw new ArgumentOutOfRangeException(nameof(fieldSource), fieldSource, null);
         }
      }

      public static IQueryable<T> FilterByValues<T>(this IQueryable<T> source,
         IEnumerable<KeyValuePair<string, object>> values, 
         Func<ParameterExpression, KeyValuePair<string, object>, Expression> fieldFunc)
      {
         var param = Expression.Parameter(typeof(T));

         foreach (var pair in values)
         {
            var fieldExpression = fieldFunc(param, pair);
            if (fieldExpression != null)
            {
               var equality = Expression.Equal(fieldExpression, Expression.Constant(pair.Value, fieldExpression.Type));
               var lambda = Expression.Lambda<Func<T, bool>>(equality, param);
               source = source.Where(lambda);
            }
         }

         return source;
      }

      public static IQueryable<T> FilterByValues<T>(this IQueryable<T> source,
         IEnumerable<KeyValuePair<string, object>> values,
         FieldSource fieldSource = FieldSource.Propety)
      {
         return FilterByValues(source, values, GetFieldFunc(fieldSource));
      }

      public static IUpdatable<T> SetValues<T>(this IUpdatable<T> source, 
         IEnumerable<KeyValuePair<string, object>> values, 
         Func<ParameterExpression, KeyValuePair<string, object>, Expression> fieldFunc)
      {
         var param = Expression.Parameter(typeof(T));
         object current = source;
         foreach (var pair in values)
         {
            var fieldExpression = fieldFunc(param, pair);
            if (fieldExpression != null)
            {
               var lambda = Expression.Lambda(fieldExpression, param);

               var method = SetMethodInfo.MakeGenericMethod(typeof(T), fieldExpression.Type);
               current = method.Invoke(null, new[] { current, lambda, pair.Value });
            }
         }

         return (IUpdatable<T>) current;
      }

      public static IUpdatable<T> SetValues<T>(this IQueryable<T> source, 
         IEnumerable<KeyValuePair<string, object>> values, 
         FieldSource fieldSource = FieldSource.Propety)
      {
         return source.AsUpdatable().SetValues(values, fieldSource);
      }

      public static IUpdatable<T> SetValues<T>(this IUpdatable<T> source, 
         IEnumerable<KeyValuePair<string, object>> values, 
         FieldSource fieldSource = FieldSource.Propety)
      {
         return SetValues(source, values, GetFieldFunc(fieldSource));
      }

      public static int UpdateDynamic<T>(this IQueryable<T> source,
         IEnumerable<KeyValuePair<string, object>> filterValues, 
         IEnumerable<KeyValuePair<string, object>> setValues, 
         FieldSource fieldSource = FieldSource.Propety)
      {
         return source
            .FilterByValues(filterValues, fieldSource)
            .SetValues(setValues, fieldSource)
            .Update();
      }

      public static Expression GetPropertyExpression(ParameterExpression instance, KeyValuePair<string, object> pair)
      {
         var propInfo = instance.Type.GetProperty(pair.Key);
         if (propInfo == null)
            return null;

         var propExpression = Expression.MakeMemberAccess(instance, propInfo);

         return propExpression;
      }

      public static Expression GetColumnExpression(ParameterExpression instance, KeyValuePair<string, object> pair)
      {
         var valueType = pair.Value != null ? pair.Value.GetType() : typeof(string);

         var method = SqlPropertyMethodInfo.MakeGenericMethod(valueType);
         var sqlPropertyCall = Expression.Call(null, method, instance, Expression.Constant(pair.Key, typeof(string)));
         var memberInfo = MemberHelper.GetMemberInfo(sqlPropertyCall);
         var memberAccess = Expression.MakeMemberAccess(instance, memberInfo);

         return memberAccess;
      }

   }
}

And usage

internal class Program
{
   public static void Main(string[] args)
   {
      using (var db = new NorthwindDB())
      {
         var filter = new Dictionary<string, object>
         {
            { "EmployeeID", 1 }
         };

         var filter2 = new Dictionary<string, object>
         {
            { "EMPLOYEEID", 1 }
         };

         var values = new Dictionary<string, object>
         {
            { "Address", "SomeAdress" },
            { "City", "SomeCity" }
         };

         db.Employees.UpdateDynamic(filter, values);

         db.Employees.UpdateDynamic(filter2, values, DynamicExtensions.FieldSource.Column);

         // OR

         db.Employees
            .FilterByValues(filter)
            .SetValues(values)
            .Update();
      }
   }
}
0reactions
MaceWinducommented, Feb 16, 2019

Closing as answered

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to create where condition from dictionary of Key and ...
How to create a where condition from the dictionary of key and value pairs? I have a dictionary that contains values for where...
Read more >
Python | Select dictionary with condition given key greater ...
Approach: Create a new empty dictionary; Iterate over the key-value pairs in the original dictionary using a for loop; If the key is...
Read more >
Dictionaries | Basics | kdb+ and q documentation
Use Dict to make a dictionary from a list of keys and a list of values. ... The lists must be the same...
Read more >
Python Dictionary Comprehension Tutorial
First, we create a dictionary named a that has three key-value pairs: 'apple': ... You often need to add conditions to a solution...
Read more >
Modifying values in a dictionary
Create a dictionary where each key is a person's name, and each value is that person's response to your question. Store at least...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found