动态查询泛型中的实体字段名称

时间:2017-06-05 13:20:51

标签: c# entity-framework generics

我正在使用泛型,因为我需要使用不同类型的数据进行大量的可重用性。我的主要问题是查询数据。我正在寻找一种方法来查询这样的东西:

public void test<T>(int id, T type) where T : class
{
    using (var ctx = myDbContext())
    {
        var myTbl = ctx.Set<T>();
        //this line gets the primary key of the table
        string key = myTbl.GetPrimaryKey(ctx);

        //this is the query I want:
        var myResult = myTbl.FirstOrDefault(x => x.key == id);

        //let's say if key = "UserId", then (x => x.UserId == id) or something that translates to this.
    }
}

我也实现了以下方法:

public object GetPropertyValue(object src, string propertyName)

我可以用它来获取特定属性的值。

但我的问题是我无法在.FirstOrDefault()调用中使用它,因为LINQ可以查询方法问题。

我目前使用此代码:

var myResult = myTbl.ToList().FirstOrDefault(x => (int)GetPropertyValue(x, key) == id);

这对于数据库中的少量行很好,但是当数据在将来增长时会对性能产生很大的影响。

P.S:我首先使用EF电动工具进行逆向工程代码

2 个答案:

答案 0 :(得分:1)

嗯,您的代码示例完全不清楚。请至少提供正确的变量名称,因为现在我甚至不知道你在哪里使用'key'变量。

此外,如果要存储和查询对象及其各种继承和嵌套的属性,请考虑使用NoSQL数据库而不是基于关系的SQL引擎。

答案 1 :(得分:0)

首先 - &gt;不要使用myTbl.ToList().FirstOrDefault(x => (int)GetPropertyValue(x, key) == id),因为它会生成一个select,它会从该表中引入所有行,然后按内存中的id进行过滤。您应该将过滤器翻译为Expression&gt;这将产生由Id列过滤的选择。

像这样构建你的linq表达式:

var x = Expression.Parameter(typeof(T), "x");

string keyPropName = type.GetPrimaryKey(ctx);
var equalExp = Expression.Equal(
    Expression.Property(x, keyPropName),
    Expression.Constant(id)
    );

var lambda = Expression.Lambda<Func<T, bool>>(equalExp, x); //x => x.Id == idValue

var myResult = myTbl.FirstOrDefault(lambda);

我使用了您的GetPropertyValueGetPrimaryKey方法。