tags:

views:

106

answers:

2

Hello,

I would like to control how linq querries my database programaticaly. For instance, I'd like to query the column X, column Y, or column Z, depending on some conditions.

First of all, I've created an array of all the properties inside my class called myPropertyInfo.

Type MyType = (typeOf(MyClass));
PropertyInfo[] myPropertyInfo = myType.GetProperties(
BindingFlags.Public|BindingFlags.Instance);

The myPropertyInfo array allows me to access each property details (Name, propertyType, etc) through the index*[i]*

Now, how can I use the above information to control how linq queries my DB?

Here's a sample of a querry I'd like to exploit.

var myVar = from tp in db.MyClass
            select tp.{expression};

Expression using myPropertyInfo[i] to choose which property(column) to query.

I'm not sure if that's the way of doing it, but if there's another way to do so, I'll be glad to learn.

=========

EDIT

I believe the right expression the one used by @Gabe. In fact, I'd like to make queries on the fly. Here's the reason: I've (i) a table "Organizations" (Ministries, Embassies, International Organizations, such as UN, UNPD, UNICEF, World Bank, etc, and services depending on them). I've (ii) an other table "Hierarchy" which represents the way those organizations are linked, starting by which category each one belongs to (Gouvernement, Foreign Missions, private sector, NGO, etc.)

Each column representing a level in the hierarchy, some rows will be longer while other will be shorter. many rows'columns will share the same value (For instance, 2 ministries belonging to the Government, will have "Government" as value for the column 'Level 1').

That's why, for each row (organization), I need to go level by level (i.e. column by column).

Hope I've been enough explicit this time

Thanks for helping.

A: 

It sounds like you want to make a Queryable on-the-fly. I haven't tried it, but this might give you a start:

var myVar = 
Queryable.Select(
    db.MyClass, 
    Expression.Property(
        Expression.Parameter(
            typeof(MyClass), // this represents the type of "tp"
            "tp"
        ),
        myPropertyInfo[i]
    )
)
Gabe
@Gabe- what expression represents in the query above???
Richard77
Richard77: `expression` is the property -- probably `myPropertyInfo[i]`
Gabe
basicaly you can use `Expression<Func<TEntity,TResult>>` , and target generic method to use it to get property name from expression, as linq does itself
vittore
A: 

if you're using Entity Framework, not LINQ to SQL, there is wonderful Entity Sql and you can use it as

object DynamicQuery(string fieldName, object fieldValue) {
    string eSql=string.Format("it.{0} = @param", fieldName);
    return db.Where(eSql, fieldValue).FirstOrDefault();
}

hope this helps

MSDN has the following example, you see that you can dynamicly change strings used to access ProductID field, and as far as i remember event rename it.

using (AdventureWorksEntities advWorksContext =
        new AdventureWorksEntities())
{
    try
    {
        // Use the Select method to define the projection.
        ObjectQuery<DbDataRecord> query =
            advWorksContext.Product.Select("it.ProductID, it.Name");

        // Iterate through the collection of data rows.
        foreach (DbDataRecord rec in query)
        {
            Console.WriteLine("ID {0}; Name {1}", rec[0], rec[1]);
        }
    }
    catch (EntitySqlException ex)
    {
        Console.WriteLine(ex.ToString());
    }
}

Also you can even do the following (again from MSDN)

using (AdventureWorksEntities advWorksContext =
    new AdventureWorksEntities())
{
    string myQuery = @"SELECT p.ProductID, p.Name FROM 
        AdventureWorksEntities.Product as p";
    try
    {
        foreach (DbDataRecord rec in
            new ObjectQuery<DbDataRecord>(myQuery, advWorksContext))
        {
            Console.WriteLine("ID {0}; Name {1}", rec[0], rec[1]);
        }
    }
    catch (EntityException ex)
    {
        Console.WriteLine(ex.ToString());
    }
    catch (InvalidOperationException ex)
    {
        Console.WriteLine(ex.ToString());
    }
}
vittore
@vitore-- fieldValue is declared but never used. obj is not declared. What's this expression "it.{0} = @param" means?
Richard77
@Richard77 - I fixed the code, in Where should be fieldValue not obj.`it.Field = @param` - is condition expressed in Entity SQL means the same as `where field = @param` - if you will use sql with params. I used string.Format because i do not like to use string operations like `"it."+fieldName+"=@param"`
vittore
@Vitore- much better. So, how do I retrieve the value? var myvar = the expression you wrote? -- var myvar = object DynamicQuery(String fieldName, etc..)?
Richard77
@Richard77 - seems i showed you only half of reciept. I added new example to answer
vittore
@Vitore--it seems like all the majick happen in the 'myQuery' string, right? Unfortunately, I don't have AdventureWorks installed in my computer. So, I'm gonna have to ask you a couple of questions. (i) If I've to change p.ProductID and p.Name by different column names, is the whole thing going to query those new specified columns? (ii)How about replacing the myQuery string by a variable that contains a string with the same information, is it gonna still be ok? If you can answer those 2 questions, that would be it
Richard77
@vitore-- In the code above ("it.ProductIB, it.Name"), what's 'it'? is that a prefix, a variable, ...?
Richard77
@Richard77 (i) you can put any column name as soon as object has it (ii) for sure you can! (iii) "it" is a prefix and means this object, a little bit strange because sql/92 doesnt need to specify table name in simple cases. "it" is default name for entity being queried.
vittore
@Vitore--I'll try it with a small and simpler Database and see what's gonna happen.
Richard77
@Richard77: We use this technique in live enterprise app and it works
vittore
@Vitore: I trust you. Anyway, I'm the one who need. By 'see what's gonna happen', I was thinking about the fact that I almost always use Linq2Sql and never Entity. So I'll do my best to do something faster.
Richard77
@Richard77, I used to use Linq2Sql in several projects, and after using EF, I can tell I like it better. It is much more flexible, and moreover it has a lot of new features in .NET 4. Also I find Entity Sql very usefull in layered applications.
vittore
@Vitore: For instance, when I create a Datacontext in Linq2Sql, I can instantiate it right away. Now, I just create 'DynamicQuery.edmx', but it's not showing up in the intellisense whereever I'm (not even in the QueryRepository, which is a class located in the Models folder - i.e. the same folder as DynamicQuery.edmx. How can I instantiate an EF?
Richard77
something with namespaces I suppose. You instantiate context like that `var advWorksContext = new AdventureWorksEntities();` just make sure entity connection string exists in .config
vittore
DynamicQueryEntities could not be found - Are you missing a directive or an assembly reference? Yet, I follwed all the step with the wizard, is there anything I forgot?
Richard77
I checked, the connection exists in the web.config, but still no DynamicQueryEntities anywher.
Richard77
I'll go to ASP.NET web site to learn some basic of EF with MVC then I'll come back here. That's much productive.
Richard77
Can you send me you testing project for a quick look ? ojosdegris at gmail dot com
vittore
I've created a new project, and everything is working now, i.e. I'm getting my Entity datacontext from the intellisense now. So, now I'm trying to get the sample you provided above work. Then, I'll get back to you in a few minutes I should know.
Richard77
Unfortunately, it's not working. I'm getting several sort of exceptions that I don't understand. What I'm going to do is to send you it via the email you provided. If you don't get now, then I'll send it tomorrow morning from the office where the connection is better.
Richard77
ok , send your db as well
vittore
I havent recieved anything yet. check the address ojosdegris at gmail
vittore
I guess I'm going to send you it tommorrow as my connection refuses to attach anything over 100kb.
Richard77
ok. Also check MSDN, it has plenty of good scenarios to use EF with.
vittore