我目前看起来有点像这样:
if(userLikesBananas)
{
return from fruit in basket
select new Fruit
{
AteBanana = Bowl.Any(b => b.OwnedBy == user && b.Contains(fruit) && fruit.Type == FruitType.Banana),
...
...
//lots of properties
...
}
}
else
{
return from fruit in basket
select new Fruit
{
AteBanana = Bowl.Any(b => b.Contains(fruit)),
...
...
//lots of properties
...
}
}
不可否认,这个例子绝对没有意义,但原则是我想根据任意标准改变属性选择的条件。现在重复选择语句。
现在我需要添加一个依赖于标准的时间了。我不希望有4种不同的情况,其中物业条件略有不同。
我想做的是这样的事情:
Func<Fruit, bool> fruitFunc = f => false;
if(userLikesBananas)
{
fruitFunc = f => Bowl.Any(b => b.OwnedBy == user && b.Contains(f) && f.Type == FruitType.Banana);
}
else
{
fruitFunc = f => Bowl.Any(b => b.Contains(f));
}
return from fruit in basket
select new Fruit
{
AteBanana = fruitFunc(fruit)
...
...
//lots of properties
...
};
麻烦的是表达式无法转换为sql,因为它包含动态调用。我尝试将Func
包裹在Expression
中,但似乎也出现了同样的问题。
所以问题是,如何避免复制和粘贴?
答案 0 :(得分:3)
...我的英语不好,但我会尝试解释如何轻松解决这个问题: - )
动态Linq不适合类型控制 - 它易于使用,但您无法浏览生成的对象(x.Name,x.Surname等)
有一个(一个类似litle noob的)技巧来解决这个问题(我正在使用它并且它的工作很费劲):
使用您选择的对象的属性创建enum
。
public enum MyAtrs {ID,FirstName,Surname}
创建Dictionary<MyAtrs,bool>
(并填写)条件(如果您想获得此属性,请设置true
)
public Dictionary Dic = new Dictionary(); Dic.Add(MyAtrs.ID,TRUE); Dic.Add(MyAtrs.Firstname,FALSE); Dic.Add(MyAtrs.Surname,TRUE);
建立您的查询:
var query = DBContext.MyDBTable.Where(predicate).Select(e =&gt; new { ID = Dic [MyAtrs.ID]? e.dbID:0, Firstname = Dic [MyAtrs.Firstname]? e.dbFirstname:空, 姓氏= Dic [MyAtrs.Surname]? e.dbSurname:空, });
在这种情况下,SQL Select语句中将有所有3列,但它只是几个字节(重要的是......)。 SQL Server会返回所有3列,但(在这种情况下)Firstname将为空(类似于{ID = 123,Firstname =,Surname =“Jobs”})。 它并不精彩但是如何在不失去类型控制的情况下构建“动态”选择表达式的简单方法:)
答案 1 :(得分:0)
我可以建议以不同的方式编写Func
(可能是这样的):
fruitFunc = f => Bowl.Any(b => ((f.Type == FruitType.Banana && b.OwnedBy == user && userLikesBananas) || !userLikesBananas) && b.Contains(f));
我没有测试它是否有效,但这可能是一种编写函数以覆盖更多情况的方法(不仅仅是2)。这个方法在某种程度上类似于我记得的布尔代数......
干杯...