给定一个具有任意属性的简单类(讨论可以说是Id,Name和Description)
并给出该类的实例,我希望通过指定匹配的属性来查找数据库中的匹配条目
我试图在这方面做一些类似于EF的AddOrUpdate方法的事情,但我需要该实体返回给我进行进一步处理。
var match = new SomeClass{Name="Whatever"};
var found = Context.SomeClass.Find(x=>x.Name, match);
public static T Find<T>(this DbSet<T> set, Expression<Func<T, object>> matchOn, T matchAgainst) where T : class {
var func = matchOn.Compile();
var valueToFind = func(matchAgainst);
var combinedExpression = //matchon + "=" + valueToFind;
var found = set.FirstOrDefault(combinedExpression);
return found;
}
这给了我传入的对象中属性的值,但我现在需要将该值与传入的表达式组合并将其传递给数据库集。
IE,我有效尝试运行的代码是set.FirstOrDefault(x=>x.Name==valueToFind)
如何使用matchon
表达式(包含x=>x.Name
)并将其与{{1}结合使用从他们那里得到==valueToFind
?
如何构建组合表达式? (我意识到&#34;字符串&#34;上面的代码是完全错误的,但我试图了解我需要该函数做什么,但我不知道那个语法会是什么样子。)
对于手动编码的示例,只需传入一个带有值集的硬编码lambda就足够了,但我的用例包括遍历一组对象并找到每个对象的匹配,因此该值不会是直到运行时才知道,并且该方法必须对任意类型和各种属性起作用,因此我也不能对属性名称进行硬编码。
答案 0 :(得分:6)
如果你有一个属性选择器和一个要比较的值,你可以得到一个这样的表达式树:
public static Func<TEntity, bool> GetComparer<TEntity,TProperty>(
Expression<Func<TEntity,TProperty>> selector, TProperty value)
{
var propertyRef = selector.Body;
var parameter = selector.Parameters[0];
var constantRef = Expression.Constant(value);
var comparer
= Expression.Lambda<Func<TEntity, bool>>
(Expression.Equal(propertyRef, constantRef), parameter)
.Compile();
return comparer;
}
样本用法:
var comparer = GetComparer<Person, string>(p => p.Name, "John");
var persons = Person.GetPersons();
var john = persons.FirstOrDefault(comparer);