2012-10-26 45 views
3

是否有可能通过PK动态执行LinQ选择?Linq Select by PK?

类似的东西:

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

你在使用EntityFramework吗? –

+0

不,我只是使用一个dbml文件;) –

回答

3

你可以尝试写一个扩展方法到您的DataContext对象,便于记录,从他们的主键数据库的拉动,由克里斯舜天在他的博客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); 

你也可能想看看丹尼斯Troller的answer作为替代。

+1

让我们试试这个,因为丹尼斯Troller的答案是从PK只有一列^^ –

+0

你的例子也只有一列作为PK,我发现了很多像这样的例子,但didn当PK包含多个列=时,找不到) –

+0

您可以修改映射对象'pkfield',而不是返回'SingleOrDefault',您可以返回'mapping.RowType.DataMembers.Any(d => d .IsPrimaryKey)'; – chridam