Передать имя свойства в метод в виде строки .NET - PullRequest
2 голосов
/ 17 января 2011

Я использую LINQ to SQL для приложения .NET MVC.

В моей базе данных есть несколько столбцов со значениями "Y" или "N".

Я пытаюсь написать метод общего назначения, который будет возвращать все записи в БД, где columnName == 'Y'

Пока у меня есть это

public IQueryable<Approved> ReturnRecordsByObjectiveFlag(string columnName)
{       
    return from approved in db.Approved
           where approved.GetType().GetProperties().Where(x => x.Name.Equals(columnName)).Equals("Y")
           select approved;
}

Но это дает мнеэта ошибка

Доступ к элементу «System.String Name» из «System.Reflection.MemberInfo» недопустим для типа «System.Reflection.PropertyInfo [].

Anyидея, где я могу пойти не так?

Спасибо.

Ответы [ 5 ]

3 голосов
/ 17 января 2011
public IQueryable<Approved> ReturnRecordsByObjectiveFlag(string columnName)
{   
    var param = Expression.Parameter(typeof(Approved), "x");
    var predicate = Expression.Lambda<Func<Approved,bool>>(
        Expression.Equal(
            Expression.PropertyOrField(param, columnName),
            Expression.Constant("Y")
        ), param);
    return db.Approved.Where(predicate);
}

Edit; если свойства на самом деле char?, т.е. 'Y' не "Y", то:

public IQueryable<Approved> ReturnRecordsByObjectiveFlag(string columnName)
{
    var param = Expression.Parameter(typeof(Approved), "x");
    Expression prop;
    var predicate = Expression.Lambda<Func<Approved, bool>>(
        Expression.Equal(
            (prop = Expression.PropertyOrField(param, columnName)),
            Expression.Constant(prop.Type == typeof(string) ?
                (object)"Y" : (object)'Y', prop.Type)
        ), param);
    return db.Approved.Where(predicate);
}

(теперь справляется со всеми string, char и char?

1 голос
/ 17 января 2011
approved.GetType().GetProperties()

вернет объект PropertyInfo []. Даже если вы фильтруете его, используя Where, оно все равно не является значением свойства, это в основном набор свойств, которые удовлетворяют критерию, даже если эта коллекция имеет только один элемент.

Чтобы получить определенное свойство по имени, лучше использовать метод GetProperty() класса Type, например:

PropertyInfo pi = approved.GetType().GetProperty(columnName);

но вы еще не закончили. Вам все еще нужно отфильтровать объекты по значению свойства, и это делается с помощью метода GetValue() для свойства, например:

bool isApproved = pi.GetValue(approved, null).Equals("Y");

или все в вашем контексте:

return from approved in db.Approved
where approved.GetType().GetProperty(columnName)
                     .GetValue(approved, null).Equals("Y")
select approved;
1 голос
/ 17 января 2011

Что не так, так это то, что вы не можете использовать отражение внутри запроса LINQ.

Сколько существует столбцов - это фиксированное относительно небольшое число? Если это так, используйте оператор switch для выбора между несколькими запросами LINQ. Это чище и намного быстрее.

Если это большое количество столбцов или они динамические, вы можете создать динамический оператор SQL, но будьте осторожны, чтобы проверить наличие возможных атак внедрения.

0 голосов
/ 17 января 2011

Это связано с тем, что последний метод Equals выполняется в отфильтрованной коллекции IQueryable вместо самого значения свойства.

Попробуйте вместо этого:

return from approved in db.Approved
               where approved.GetType().GetProperties().Where(x => x.Name.Equals(columnName) && (string)x.GetValue(db.Approved, null) == "Y")
               select approved;
0 голосов
/ 17 января 2011
  • GetType() возвращает Type

  • GetProperties() возвращает PropertyInfo[]

  • Where(..) возврат IEnumerable<PropertyInfo>

так вы звоните

IEnumerable<PropertyInfo>.Equals(string)

это кажется неправильным. Не так ли?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...