Общий метод расширения DbLinq - строка в качестве селектора ключей?

Следующий фрагмент показывает, что я хочу:

public static class DblinqExtension
{
    public static int MaxId<T>(this DbLinq.Data.Linq.Table<T> table) where T : class
    {
        var val = table.OrderByDescending(x => "Id").FirstOrDefault();
        return Convert.ToInt32(val);
    }
}

С помощью DbMetal я создал классы сопоставления. Каждая таблица, которая у меня есть, имеет идентификатор столбца (который, очевидно, является целым числом), и я хочу знать максимальный идентификатор.

Кто-нибудь знает, как я могу заставить работать свой фрагмент ??

Спасибо!


Я нашел эту статью: OrderBy с помощью String keySelector

С этим предложением мой код станет:

public static int MaxId<T>(this DbLinq.Data.Linq.Table<T> table) where T : class
{
    var val = table.OrderByDescending(CreateSelectorExpression<T>("Id")).FirstOrDefault();
    return Convert.ToInt32(val);
}

private static Expression<Func<T, Int32>> CreateSelectorExpression<T>(string propertyName) where T : class
{
    var parameterExpression = Expression.Parameter(typeof(T));
    return (Expression<Func<T, Int32>>)Expression.Lambda(
        Expression.PropertyOrField(parameterExpression, propertyName), 
        parameterExpression
    );
}

НО теперь я получаю сообщение об ошибке:

Значение не может быть нулевым. Имя параметра: ключ


person 321X    schedule 20.07.2011    source источник


Ответы (2)


не уверен но попробуй

var Result = from x in table select x.Max ( x => x.Id );

РЕДАКТИРОВАТЬ - если вам нужно взять Id как строку в выражение:

var Result = from x in table select x.Max ( x => x.GetType().GetProperty ("Id").GetGetMethod().Invoke (x, null) );

РЕДАКТИРОВАТЬ - если вам нужно разделить:

var Result1 = from x in table select x; var Result2 = Result1.Max(x => x.GetType().GetProperty("Id").GetGetMethod().Invoke(x, null)); 

РЕДАКТИРОВАТЬ - если "Id" - это поле, вам нужно это:

var Result1 = from x in table select x; 
var Result2 = Result1.Max(x => x.GetType().GetField ( "Id" ).GetValue(x));
person Yahia    schedule 20.07.2011
comment
Откуда взялся _x?? И таблица является универсальной, кстати, класса типов - person 321X; 21.07.2011
comment
Мне нужно разделить var Result1 = from x in table select x; var Result2 = Result1.Max(x => x.GetType().GetProperty("ID").GetGetMethod().Invoke(x, null)); Теперь я получаю параметр ArgumentException was unhandled - person 321X; 21.07.2011
comment
см. мое редактирование - во втором выражении вы используете Result, где вам нужно использовать Result1 - person Yahia; 21.07.2011
comment
Да, опечатка на моей стороне! Если это была ошибка, код не скомпилировался. Код компилируется и ошибка появляется во время выполнения! - person 321X; 21.07.2011
comment
не уверен, но в своем коде вы пишете идентификатор, а в своем исходном сообщении вы написали идентификатор ... возможно, это причина? - person Yahia; 21.07.2011
comment
Теперь это ID, потому что Id дал такое же исключение... Так что никакой разницы, используя Id или ID - person 321X; 21.07.2011
comment
@Yahia, давайте продолжим обсуждение в чате - person 321X; 21.07.2011

Ладно, я разобрался!!

    public static int MaxId<T>(this DbLinq.Data.Linq.Table<T> table) where T : class
    {
        var param = Expression.Parameter(typeof(T), "p");
        var body = Expression.PropertyOrField(param, "ID");
        var lambda = Expression.Lambda<Func<T, int>>(body, param);

        var val = table.OrderByDescending(lambda).FirstOrDefault();
        return Convert.ToInt32(val.GetType().GetProperty("ID").GetGetMethod().Invoke(val, null));
    }

Большое спасибо @Yahia за подсказку с частью GetProperty!

person 321X    schedule 21.07.2011