8

I have a table where I want to make a query on variable columns. Like:

private void query(string column, string value) {

    using (var db = new myDB()) {

        var s1 = (from c in db.Components
                  where (**column** == **value**)
                  select new {c.id, **column**});
    }
}

lets say I want to look for a supplier then it would be like:

var s1 = (from c in db.Components
          where (c.supplier == "abc")
          select new {c.id, c.supplier});

is there a way to pass the column name as variable?

davmos
  • 9,324
  • 4
  • 40
  • 43
Patrick
  • 145
  • 1
  • 1
  • 9
  • please see [this SO question](http://stackoverflow.com/questions/2148309/how-do-i-reference-a-field-in-linq-based-on-a-dynamic-fieldname) – Muhammad Mamoor Khan Sep 12 '13 at 10:57
  • and please do a proper search before posting a new question here at SO, because it hurts your repo – Muhammad Mamoor Khan Sep 12 '13 at 10:58
  • You can also use [Dynamic Query library](http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx) – Nilesh Sep 12 '13 at 11:05

5 Answers5

5

This example can be useful i guess.

 void BindGridTypeSafe()
    {
        NorthwindDataContext northwind = new NorthwindDataContext();

        var query = from p in northwind.Products
                    where p.CategoryID == 3 && p.UnitPrice > 3
                    orderby p.SupplierID
                    select p;

        GridView1.DataSource = query;
        GridView1.DataBind();
    }

    void BindGridDynamic()
    {
        NorthwindDataContext northwind = new NorthwindDataContext();

        var query = northwind.Products
                             .Where("CategoryID = 3 AND UnitPrice > 3")
                             .OrderBy("SupplierID");

        GridView1.DataSource = query;
        GridView1.DataBind();
    }
Burk
  • 2,969
  • 1
  • 23
  • 24
  • 1
    thx for the example, i tried that out but it threw me an exception. I found out that since im using entityframework it's mandatory to write it.COLUMNNAME (it.supplier). that solved my problem with using dynamic linq. THX! – Patrick Sep 12 '13 at 11:12
  • This is used by adding Linq.Dynamic namespace. – Faraz Ahmed Dec 31 '19 at 05:05
3

A nice way is to use Dynamic Linq

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

Something like:

var s1 = (from c in db.Components
    where(column + "=" + value)
    select new {c.id, **column**});
Dave Bish
  • 19,263
  • 7
  • 46
  • 63
1

Short answer is to add library System.Linq.Dynamic as a reference and do:

string columnName = "Supplier";
var s1 = Suppliers
    .Where(String.Format("{0} == \"abc\"", columnName))
    .Select(new {c.id, c.supplier};

Following is a complete working example of Dynamic Linq, where column-name is a parameter:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic;

public class Program
{
    public static void Main()
    {
        var lstContacts = new List<Contact>{
            new Contact{Id = 1, Active = true, Name = "Chris"}, 
            new Contact{Id = 2, Active = true, Name = "Scott"}, 
            new Contact{Id = 3, Active = true, Name = "Mark"}, 
            new Contact{Id = 4, Active = false, Name = "Alan"}};

        string columnName = "Active";
        List<Contact> results = lstContacts.Where(String.Format("{0} == true", columnName)).ToList();

        foreach (var item in results)
        {
            Console.WriteLine(item.Id.ToString() + " - " + item.Name.ToString());
        }
    }
}

public class Contact
{
    public int Id
    {
        get;
        set;
    }

    public bool Active
    {
        get;
        set;
    }

    public string Name
    {
        get;
        set;
    }
}

You can experiment with this .net-fiddle-here

cnom
  • 3,071
  • 4
  • 30
  • 60
1

I'm resurrecting this old thread because I had to work around that issue with ASP.NET Core 2.2 today. I used the System.Linq.Dynamic.Core NuGet package to create the following extension method, which works beautifully if you need to check if multiple given string values are contained within multiple given columns.

public static IQueryable<TEntity> WhereContains<TEntity>(
    this IQueryable<TEntity> query,
    string field,
    string value,
    bool throwExceptionIfNoProperty = false,
    bool throwExceptionIfNoType = false)
    where TEntity : class
{
    PropertyInfo propertyInfo = typeof(TEntity).GetProperty(field);
    if (propertyInfo != null)
    {
        var typeCode = Type.GetTypeCode(propertyInfo.PropertyType);
        switch (typeCode)
        {
            case TypeCode.String:
                return query.Where(String.Format("{0}.Contains(@0)", field), value);
            case TypeCode.Boolean:
                var boolValue = (value != null
                    && (value == "1" || value.ToLower() == "true"))
                    ? true
                    : false;
                return query.Where(String.Format("{0} == @0", field), boolValue);
            case TypeCode.Int16:
            case TypeCode.Int32:
            case TypeCode.Int64:
            case TypeCode.UInt16:
            case TypeCode.UInt32:
            case TypeCode.UInt64:
                return query.Where(String.Format("{0}.ToString().Contains(@0)", field), value);

            // todo: DateTime, float, double, decimals, and other types.

            default:
                if (throwExceptionIfNoType)
                    throw new NotSupportedException(String.Format("Type '{0}' not supported.", typeCode));
                break;
        }
    }
    else
    {
        if (throwExceptionIfNoProperty)
            throw new NotSupportedException(String.Format("Property '{0}' not found.", propertyInfo.Name));
    }
    return query;
}

The code can be used with .NETStandard/.NETCore (using the aforementioned System.Linq.Dynamic.Core package) and also with ASP.NET 4.x (using the System.Linq.Dynamic package).

For further info regarding the WhereContains extension method and a full use-case info, check out this post on my blog.

Darkseal
  • 9,205
  • 8
  • 78
  • 111
0

Just use typeof to use the column name

public string columnName(string Id, string columnName, string columndata)
        {
            var story = _CidbContext.Stories.Where(m => m.Id.ToString() == Id).FirstOrDefault();
            var property = typeof(Story).GetProperty(columnName);
            if (property != null)
            {

                var convertedValue = Convert.ChangeType(columndata, property.PropertyType);

                property.SetValue(story, convertedValue);
                _CidbContext.SaveChanges();
                return "Data Saved";
            }
            return "No Column found";
        }