Friday, January 09, 2009 5:02 PM
lukaashek
LINQ to SQL + Reflexe
Při vývoji aplikace, která obsahuje docela hodně tabulek jsem se dostal do situace, kdy jsem potřeboval vrátit konkrétní položku podle ID. Nechtělo se mi ovšem pro každou z X tříd psát metodu, která bude dělat pořád to stejné.
Vytvořil jsem si tedy generickou metodu GetObjectByID
public static T GetObjectByID<T>(int id) where T : class
{
if (id < 0)
throw new ArgumentException("id");
Type objectType = typeof(T);
Type columnType = typeof (ColumnAttribute);
// ziskam si sloupec PK
PropertyInfo pkProperty = objectType.GetProperties().Where(
prop => prop.GetCustomAttributes(typeof (ColumnAttribute), false).First() != null &&
((ColumnAttribute) prop.GetCustomAttributes(typeof (ColumnAttribute), false).First()).
IsPrimaryKey
).First();
// vytvorim si vyraz
ParameterExpression parameter = ParameterExpression.Parameter(objectType, "CurentTable");
var predicate = Expression.Lambda<Func<T, bool>>(Expression.Equal(
Expression.Property(parameter, objectType.GetProperty(pkProperty.Name)),
Expression.Constant(id)),
parameter);
return Db.GetTable<T>().Where(predicate).FirstOrDefault();
}
Jelikož potřebuju hledat podle ID, tak si z konkrétního objektu musím najít takovou vlastnost, která je označena atributem CollumnAttribute a zárověn je i primární klíč. Jakmile mám nalezenou konkrétní vlastnost, tak si vytvořím predikát, který obsahuje výraz pro porovnání mojí nalezené vlastnost (PK) s id, které je parametrem mojí metody.
Na základě generického typu T si získám tabulku a na konkrétní tabulce zavolám extensní metodu Where, kde jí jako parametr předám ten můj predikát. Nyní už jen vrátím výsledek a je to. Myslím si, že to ušetří docela dost času :-)
Ještě zde přidám ukázku, jak provádět hledání podle více ID, ale to už je jednodušší
public static IQueryable<T> GetObjectsByID<T>(IEnumerable<int> ids) where T : class
{
List<T> result = new List<T>();
foreach (var id in ids)
{
result.Add(GetObjectByID<T>(id));
}
return result.AsQueryable();
}
Lukáš