3

LinQ select by PK を動的に実行することは可能ですか?

そんな感じ :

public T FindByPK(IEnumerable<T> table, T itemToFind)
{

}

T はテーブルからのマッピングです (LinQ から SQL 自動生成)。

リフレクションを使用してみましたが、PK に複数の列が含まれている場合があるため、属性「IsPrimaryKey」を取得して LinQ を実行する方法がわかりません。

chridamによる回答後に編集

したがって、GetByPK を実行できるようになりましたが、PK は 1 つの列のみであると想定しています...

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);
        }

そのため、多数のプロパティのグループではなく、1 つのプロパティのみを必要とする Expression.Property に行き詰まっています。

4

1 に答える 1

3

DataContextChris 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 に答える