【问题标题】:Filter in linQ c# with dynamic properties使用动态属性过滤 linQ c#
【发布时间】:2016-11-16 18:15:37
【问题描述】:

我有一个属性列表

string[] strings =
{
    "State", "Name","Location"
};

它们都在字符串类型的Test对象中,我需要先循环抛出它们并在属性等于“OK”时过滤数据

这是我的代码 sn-p

for (int x=0;x<strings.Length;x++)
{
    // PropertyDescriptor prop = TypeDescriptor.GetProperties(typeof(Test)).Find(strings[x],true);                                               

    var miss = _unityOfWork.TestRepository.Get(i =>
                   i.GetType().GetProperty(strings[x]).Equals("OK") )
                   .Select().toList()

此代码返回以下异常:

“LINQ to Entities 无法识别方法 'System.Reflection.PropertyInfo GetRuntimeProperty(System.Type, System.String)' 方法,并且该方法无法转换为存储表达式。”

我需要用数组中的属性名过滤列表

【问题讨论】:

  • 您的 TestRepository 到底是什么?它是如何实现的?
  • 我想你的意思是说当属性value等于“OK”,对吧?
  • @EduardMalakhov 它继承自 GenericRepository
  • LINQ 正在尝试将表达式 i.GetType().GetProperty(strings[x]).Equals("OK") 转换为数据库查询(通常是 SQL),这是错误中的 store expression 部分。然而,第一个支持 .NET 反射的数据库还没有被发明出来……
  • @wdosanjos 对,Test 类有 3 个属性,当它们等于“OK”时,我需要验证它们

标签: c# entity-framework linq properties


【解决方案1】:

我可能会这样做...简单明了,没有反射,开关有两个功能:(1)防止未知字段,(2)为每种情况应用适当的条件。

var strings = new[] { "State", "Name", "Location" };

var result = _unityOfWork.TestRepository.GetAll().AsQueryable();
// you may need to tweak the above before it works

foreach (var field in strings)
{
    switch (field)
    {
        case "State":
            result = result.Where(x => x.State == "OK");
            break;
        case "Name":
            result = result.Where(x => x.Name == "OK");
            break;
        case "Location":
            result = result.Where(x => x.Location == "OK");
            break;
    }
}

return result;   // if needed, add .ToList() or .ToArray() 

【讨论】:

    【解决方案2】:

    您可能会执行以下操作:

    public string ValidateProperty<T>(T parameter)
    {
         var properties = typeof(...).GetProperties();
         foreach(var property in properties)
              if(property == parameter)
                  return "OK";
    
         return "FAIL";
    }   
    
    var content = collection.Get().Where(property => ValidateProperty(property.Name.Value) == "OK" && ValidateProperty(property.State.Value) == "OK");
    

    没有时间检查语法,但这应该可以让您比较所有内容。陷阱是每次调用都会生成一个PropertyInfo 数组。一个想法或不同的方法,但不确定它对您的实施是否可行。

    【讨论】:

      【解决方案3】:

      由于OP表示属性始终相同,请尝试以下操作:

      var miss = _unitOfWork.TestRepository
                            .Where(m => m.State == "OK" || m.Name == "OK" || m.Location == "OK");
      

      【讨论】:

      • 每个有效属性的每个测试都需要一行
      • 将 &amp;&amp; 更改为 || 以满足您的测试要求。
      • 当投影无法准确到达条件发生的位置时仍然存在问题
      【解决方案4】:

      你可以这样做(不确定确切的语法,但想法):

      var miss = _unityOfWork.TestRepository.Get()
      
                         .Where(i => i.GetType().GetProperty(strings[x]).Equals("OK"))
                         .toList()
      

      编辑: 正确的选项类似于

      var miss = _unityOfWork.TestRepository
                      .ToList()
                      .Where(i => i.GetType().GetProperty(strings[x]).Equals("OK"))
                      .toList()
      

      【讨论】:

      • 谢谢...但还是一样
      • @AbdouTelb 抱歉,我在中间丢失了 ToList 调用。
      猜你喜欢
      • 2021-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多