3

是否可以通过 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 中,他们只需要一个属性而不是一组属性。

4

1 回答 1

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 的答案作为替代方案。

于 2012-10-26T08:52:59.043 回答