是否可以通过PK动态执行LinQ选择?
类似的东西:
public T FindByPK(IEnumerable<T> table, T itemToFind)
{
}
T是从表(LinQ到SQL自动生成)的映射。
我尝试使用反射,但我不知道如何获取属性“IsPrimaryKey”,然后执行LinQ,因为有时PK包含多个列。
在chridam回答之后编辑
所以,我现在可以做一个GetByPK,但它假设PK只有一列......
public static class DataContextHelpers
{
public static T GetByPk<T>(this DataContext context, object pk) where T : class {
var table = context.GetTable<T>();
var mapping = context.Mapping.GetTable(typeof(T));
var pkfield = mapping.RowType.DataMembers.SingleOrDefault(d => d.IsPrimaryKey);
if (pkfield == null)
throw new Exception(String.Format("Table {0} does not contain a Primary Key field", mapping.TableName));
var param = Expression.Parameter(typeof(T), "e");
var predicate = Expression.Lambda<Func<T, bool>>(Expression.Equal(Expression.Property(param, pkfield.Name), Expression.Constant(pk)), param);
return table.SingleOrDefault(predicate);
}
}
我更改了这样的代码,以便能够获取主键的所有列,而且,对象pk必须是表的一行(因为我不知道什么是pk列)
public static T GetByPk<T>(this DataContext context, T row) where T : class
{
var table = context.GetTable<T>();
var mapping = context.Mapping.GetTable(typeof(T));
var pkfield = mapping.RowType.DataMembers.Where(d => d.IsPrimaryKey);
if (!pkfield.Any())
throw new Exception(String.Format("Table {0} does not contain a Primary Key field", mapping.TableName));
var param = Expression.Parameter(typeof(T), "e");
var predicate = Expression.Lambda<Func<T, bool>>(Expression.Equal(Expression.Property(param, pkfield??), Expression.Property(param, row??)), param);
return table.SingleOrDefault(predicate);
}
所以,我被困在Expression.Property,他只需要一个属性,而不是一组很多。
答案 0 :(得分:3)
您可以尝试在DataContext
对象上编写扩展方法,以便通过主键从数据库中提取记录,正如Chris Sainty在其博客文章LINQ to SQL: Generic Primary Key function中所述:
public static class DataContextHelpers
{
public static T GetByPk<T>(this DataContext context, object pk) where T : class {
var table = context.GetTable<T>();
var mapping = context.Mapping.GetTable(typeof(T));
var pkfield = mapping.RowType.DataMembers.SingleOrDefault(d => d.IsPrimaryKey);
if (pkfield == null)
throw new Exception(String.Format("Table {0} does not contain a Primary Key field", mapping.TableName));
var param = Expression.Parameter(typeof(T), "e");
var predicate = Expression.Lambda<Func<T, bool>>(Expression.Equal(Expression.Property(param, pkfield.Name), Expression.Constant(pk)), param);
return table.SingleOrDefault(predicate);
}
}
然后通过以下方式调用该方法:
MyDataContext db = new MyDataContext();
Product p = db.GetByPk<Product>(1);
您可能还想看看Denis Troller的answer作为替代方案。