如何使用反射和LINQ to Entities来获得实体属性';s值
本文关键字:属性 实体 反射 何使用 LINQ to Entities | 更新日期: 2023-09-27 18:25:10
我尝试执行以下语句:
int count = this.objectReportsRepository.All()
.Count(or => (int)or.GetPropertyValue("ReportingUserId") == reportModel.ReportingUserId
&& or.GetPropertyValue("Reported" + target + "Id") == reportModel.GetPropertyValue("Reported" + target + "Id")
&& DbFunctions.TruncateTime((DateTime)or.GetPropertyValue("ReportDate")) == serverTimeToday);
但是,我得到一个错误:System.NotSupportedException:LINQ to Entities无法识别方法"System.Object GetPropertyValue[QuestionReport](InterpretumDAL.QuestionReport,System.String)",并且此方法无法转换为存储表达式
GetPropertyValue实际上是我自己编写的用于使用反射的扩展方法:
public static object GetPropertyValue<T>(this T sourceObject, string propertyName)
{
return sourceObject.GetType().GetProperty(propertyName).GetValue(sourceObject, null);
}
我想执行写在问题顶部的LINQ to Entitys语句,因为我有不同的Report实体。例如,我有QuestionReport、UserReport、TagReport等实体。我对它们做的都是一样的,但它们有不同的含义。QuestionReport实体存储Question实体的报告。UserReport-用于用户实体等等。因此,我不想多次编写相同的代码n,而是希望使用Reflection。
我唯一能想到的就是在All()方法调用之后添加一个ToList()法调用,但通过这样做,我实际上加载了内存中的所有实体,并且只有在这之后我才计算我想要计数的东西,而不是用简单的查询来计算它。
帮助?有人吗?:)
您需要构建表达式树,以便将其用于linq-to实体,请尝试此表达式。
var or = Expression.Parameter(typeof(ObjectReport));
var cond1 = Expression.Equal(
Expression.Property(or, "ReportingUserId"),
Expression.Constant(reportModel.ReportingUserId));
var cond2 = Expression.Equal(
Expression.Property(or, "Reported" + target + "Id"),
Expression.Constant(reportModel.GetPropertyValue("Reported" + target + "Id")));
var cond3 = Expression.Equal(
Expression.Call(
typeof(DbFunctions),
"TruncateTime",
Type.EmptyTypes,
Expression.Convert(Expression.Property(or, "ReportDate"), typeof(DateTime?))),
Expression.Convert(Expression.Constant(serverTimeToday), typeof(DateTime?)));
var cond = Expression.AndAlso(Expression.AndAlso(cond1, cond2), cond3);
var predicate = Expression.Lambda<Func<ObjectReport, bool>>(cond, or);
int count = this.objectReportsRepository.All().Count(predicate);
无意冒犯,但如果要像这样滥用泛型,为什么还要使用实体框架呢?
你的存储库应该是Repository<T>
,这样当你执行.All()时,你就可以通过Func直接选择你需要的属性值。然后,在您的代码中,无论您在哪里需要Repository<QuestionReport>
,一切都会自动设置,您的查询只需执行
var questions = repository.All(questionReport => questionReport.Question == "How old are you");
您应该永远不要在任何类型的循环中使用反射。这是非常低效的。
无论如何,如果你仍然坚持这一点,你就必须执行.All().ToList(),然后再次循环它来执行你的逻辑,因为(要重新写入):你做得非常非常错误。