我正在用我的代码编写查询,这是Linq to Sql。我对表达式不是很熟悉,我想写一个表达式来检查IEnumerable中的任何一项是否满足条件
public class TestClass1
{
// can be any number of properties, with diff names and types
public string TestProperty1 { get; set; }
public string TestProperty2 { get; set; }
public List<TestClass1ExtraFieldValue> TestClass1ExtraFieldValueList { get; set; }
}
public class TestClass1ExtraFieldValue
{
public TestClass1ExtraField TestClass1ExtraField { get; set; }
// property names below are same in all classes which name ends with ExtraFieldValue
public int IntValue { get; set; }
public bool BoolValue { get; set; }
public DateTime DateTimeValue { get; set; }
public string StringValue { get; set; }
}
public class TestClass1ExtraField
{
// property names are same in all classes which name ends with ExtraField
public string Property1 { get; set; }
public string Property2 { get; set; }
}
public class TestClass2
{
// can be any number of properties, with diff names and types
public string TestProperty1 { get; set; }
public string TestProperty2 { get; set; }
public List<TestClass2ExtraFieldValue> TestClass2ExtraFieldValueList { get; set; }
}
public class TestClass2ExtraFieldValue
{
public TestClass2ExtraField TestClass2ExtraField { get; set; }
// property names below are same in all classes which name ends with ExtraFieldValue
public int IntValue { get; set; }
public bool BoolValue { get; set; }
public DateTime DateTimeValue { get; set; }
public string StringValue { get; set; }
}
public class TestClass2ExtraField
{
// property names are same in all classes which name ends with ExtraField
public string Property1 { get; set; }
public string Property2 { get; set; }
}
public class TestClass3
{
// can be any number of properties, with diff names and types
public string TestProperty1 { get; set; }
public string TestProperty2 { get; set; }
public List<TestClass3ExtraFieldValue> TestClass3ExtraFieldValueList { get; set; }
}
public class TestClass3ExtraFieldValue
{
public TestClass3ExtraField TestClass3ExtraField { get; set; }
// property names below are same in all classes which name ends with ExtraFieldValue
public int IntValue { get; set; }
public bool BoolValue { get; set; }
public DateTime DateTimeValue { get; set; }
public string StringValue { get; set; }
}
public class TestClass3ExtraField
{
// property names are same in all classes which name ends with ExtraField
public string Property1 { get; set; }
public string Property2 { get; set; }
}
// NOT a DB class
public class ExtraFieldClass
{
public string Property1 { get; set; }
public string Property2 { get; set; }
public int IntValue { get; set; }
public bool BoolValue { get; set; }
public DateTime DateTimeValue { get; set; }
public string StringValue { get; set; }
}我有如下查询类:
public class TestClass1Query
{
public string TestValue1;
public string TestValue2;
List<ExtraFieldClass> ExtraFieldsList { get; set; }
public IQueryable GetQuery()
{
var query = GetTestClass1Values().Where(c=> c.TestProperty1==TestValue1 && c.TestProperty2 == TestValue2);
// some condition checks
foreach (var extraField in ExtraFieldsList)
{
switch (extraField.Type)
{
case FieldType.Boolean:
{
var boolValue = Convert.ToBoolean(extraField.Fieldvalue);
query = query.Where(c => c.TestClass1ExtraFieldValueList.Any(t => t.TestClass1ExtraField.Property1 == extraField.Property1
&& t.TestClass1ExtraField.Property2 == extraField.Property2
&& t.BoolValue == boolValue));
break;
}
case FieldType.DateTime:
{
var dateTimeValue = Convert.ToDateTime(extraField.Fieldvalue);
query = query.Where(c => c.TestClass1ExtraFieldValueList.Any(t => t.TestClass1ExtraField.Property1 == extraField.Property1
&& t.TestClass1ExtraField.Property2 == extraField.Property2
&& t.DateTimeValue == dateTimeValue));
break;
}
case FieldType.Text:
{
var stringValue = Convert.ToString(extraField.Fieldvalue);
query = query.Where(c => c.TestClass1ExtraFieldValueList.Any(t => t.TestClass1ExtraField.Property1 == extraField.Property1
&& t.TestClass1ExtraField.Property2 == extraField.Property2
&& t.StringValue == stringValue));
break;
}
case FieldType.Integer:
{
var integerValue = Convert.ToInt32(extraField.Fieldvalue);
query = query.Where(c => c.TestClass1ExtraFieldValueList.Any(t => t.TestClass1ExtraField.Property1 == extraField.Property1
&& t.TestClass1ExtraField.Property2 == extraField.Property2
&& t.IntValue == integerValue));
break;
}
}
}
return query;
}
private IQueryable<TestClass1> GetTestClass1Values()
{
return null;
}
}
public class TestClass2Query
{
public string TestValue1;
public string TestValue2;
List<ExtraFieldClass> ExtraFieldsList { get; set; }
public IQueryable GetQuery()
{
var query = GetTestClass2Values().Where(c => c.TestProperty1 == TestValue1 && c.TestProperty2 == TestValue2);
// some condition checks
foreach (var extraField in ExtraFieldsList)
{
switch (extraField.Type)
{
case FieldType.Boolean:
{
var boolValue = Convert.ToBoolean(extraField.Fieldvalue);
query = query.Where(c => c.TestClass2ExtraFieldValueList.Any(t => t.TestClass2ExtraField.Property1 == extraField.Property1
&& t.TestClass2ExtraField.Property2 == extraField.Property2
&& t.BoolValue == boolValue));
break;
}
case FieldType.DateTime:
{
var dateTimeValue = Convert.ToDateTime(extraField.Fieldvalue);
query = query.Where(c => c.TestClass2ExtraFieldValueList.Any(t => t.TestClass2ExtraField.Property1 == extraField.Property1
&& t.TestClass2ExtraField.Property2 == extraField.Property2
&& t.DateTimeValue == dateTimeValue));
break;
}
case FieldType.Text:
{
var stringValue = Convert.ToString(extraField.Fieldvalue);
query = query.Where(c => c.TestClass2ExtraFieldValueList.Any(t => t.TestClass2ExtraField.Property1 == extraField.Property1
&& t.TestClass2ExtraField.Property2 == extraField.Property2
&& t.StringValue == stringValue));
break;
}
case FieldType.Integer:
{
var integerValue = Convert.ToInt32(extraField.Fieldvalue);
query = query.Where(c => c.TestClass2ExtraFieldValueList.Any(t => t.TestClass2ExtraField.Property1 == extraField.Property1
&& t.TestClass2ExtraField.Property2 == extraField.Property2
&& t.IntValue == integerValue));
break;
}
}
}
return query;
}
private IQueryable<TestClass2> GetTestClass2Values()
{
return null;
}
}
public class TestClass3Query
{
public string TestValue1;
public string TestValue2;
List<ExtraFieldClass> ExtraFieldsList { get; set; }
public IQueryable GetQuery()
{
var query = GetTestClass3Values().Where(c => c.TestProperty1 == TestValue1 && c.TestProperty2 == TestValue2);
// some condition checks
foreach (var extraField in ExtraFieldsList)
{
switch (extraField.Type)
{
case FieldType.Boolean:
{
var boolValue = Convert.ToBoolean(extraField.Fieldvalue);
query = query.Where(c => c.TestClass3ExtraFieldValueList.Any(t => t.TestClass3ExtraField.Property1 == extraField.Property1
&& t.TestClass3ExtraField.Property2 == extraField.Property2
&& t.BoolValue == boolValue));
break;
}
case FieldType.DateTime:
{
var dateTimeValue = Convert.ToDateTime(extraField.Fieldvalue);
query = query.Where(c => c.TestClass3ExtraFieldValueList.Any(t => t.TestClass3ExtraField.Property1 == extraField.Property1
&& t.TestClass3ExtraField.Property2 == extraField.Property2
&& t.DateTimeValue == dateTimeValue));
break;
}
case FieldType.Text:
{
var stringValue = Convert.ToString(extraField.Fieldvalue);
query = query.Where(c => c.TestClass3ExtraFieldValueList.Any(t => t.TestClass3ExtraField.Property1 == extraField.Property1
&& t.TestClass3ExtraField.Property2 == extraField.Property2
&& t.StringValue == stringValue));
break;
}
case FieldType.Integer:
{
var integerValue = Convert.ToInt32(extraField.Fieldvalue);
query = query.Where(c => c.TestClass3ExtraFieldValueList.Any(t => t.TestClass3ExtraField.Property1 == extraField.Property1
&& t.TestClass3ExtraField.Property2 == extraField.Property2
&& t.IntValue == integerValue));
break;
}
}
}
return query;
}
private IQueryable<TestClass3> GetTestClass3Values()
{
return null;
}
}现在,如果您看到我的查询类,每个类都有自己的条件检查,并且对于额外的字段,逻辑是相同的,只是名称发生了变化。我有20个类似的班级。我不想在任何地方都有相同的重复代码。我搜索了一下,才知道我们可以使用linq-expressions来实现这一点。
我对写表达式一无所知,有什么建议或方法可以做到这一点吗?
发布于 2015-05-29 15:49:27
您编写的Linq实际上被转换为SQL命令。在您的例子中,您已经创建了相当复杂的Match函数,它太复杂了,无法自动转换成SQL语句。
要解决这个问题,您必须从Match方法中提取switch语句并创建内联查询:
var input = new Parameter();
// ...init input
query = query.Where(a => a.Property1 == "sometext");
switch(input.Type)
{
Case bool:
var boolValue = Convert.ToBoolean(input.ObjectValue);
query = query.Where(a => a.Collection.Any(b => b.TestValue.C1 == input.Parameter1 && b.TestValue.C2 == input.Parameter && b.BoolValue == boolValue);
break;
Case dateTime :
// convert to datetime and check
var dateTimeValue = Convert.ToDateTime(input.ObjectValue);
query = query.Where(a=> a.Collection.Any(b => b.TestValue.C1 == input.Parameter1 && b.TestValue.C2 == input.Parameter && b.DateTimeValue == dateTimeValue );
break;
Case int:
// convert to int and check
// ...
break;
}看起来不是最好的代码,但它应该可以工作。
编辑
你可以通过将丑陋的部分移到可重用的分离函数中来改进它:
public IQueryable<ITest2> ApplyFilterOnQuery(IQueryable<ITest2> query, Parameter input)
{
switch(input.Type)
{
Case bool:
var boolValue = Convert.ToBoolean(input.ObjectValue);
query = query.Where(a => a.Collection.Any(b => b.TestValue.C1 == input.Parameter1 && b.TestValue.C2 == input.Parameter && b.BoolValue == boolValue);
break;
Case dateTime :
// convert to datetime and check
var dateTimeValue = Convert.ToDateTime(input.ObjectValue);
query = query.Where(a => a.Collection.Any(b => b.TestValue.C1 == input.Parameter1 && b.TestValue.C2 == input.Parameter && b.DateTimeValue == dateTimeValue );
break;
Case int:
// convert to int and check
// ...
break;
}
return query;
}然后,您可以这样使用它:
var input = new Parameter();
// ...init input
query = query.Where(a => a.Property1 == "sometext");
query = ApplyFilterOnQuery(query, input);https://stackoverflow.com/questions/30522247
复制相似问题