This is probably a basic LINQ question. I have need to select one object and if it is null select another. I'm using linq to objects in the following way, that 开发者_如何学JAVAI know can be done quicker, better, cleaner...
public Attrib DetermineAttribution(Data data)
{
var one = from c in data.actions
where c.actionType == Action.ActionTypeOne
select new Attrib
{
id = c.id,
name = c.name
};
if( one.Count() > 0)
return one.First();
var two = from c in data.actions
where c.actionType == Action.ActionTypeTwo
select new Attrib
{
id = c.id,
name = c.name
};
if (two.Count() > 0 )
return two.First();
}
The two linq operations differ only on the where clause and I know there is a way to combine them. Any thoughts would be appreciated.
I think this solution is simple and efficient:
public Attrib DetermineAttribution(Data data)
{
var c = data.actions.FirstOrDefault(c => c.actionType == Action.ActionTypeOne) ??
data.actions.FirstOrDefault(c => c.actionType == Action.ActionTypeTwo);
return c != null ? new Attrib { id = c.id, name = c.name } : null;
}
This doesn't use the query syntax, but it preserves the logic that an element of type ActionTypeOne is return before an element of ActionTypeTwo. And because of lazy evaluation, the second query won't be executed unless there are no elements of type ActionTypeOne.
public Attrib DetermineAttribution(Data data)
{
return data.actions.Where( c => c.actionType == Action.ActionTypeOne)
.Concat( data.actions.Where( c.actionType == Action.ActionTypeTwo ) )
.Select( c => new Attrib
{
id = c.id,
name = c.name
})
.FirstOrDefault();
}
var one = (from c in data.actions
where (c.actionType == Action.ActionTypeOne) || (c.actionType == Action.ActionTypeTwo)
select new Attrib
{
id = c.id,
name = c.name
}).FirstOrDefault();
This does not guarantee that ActionTypeOne will be found before ActionTypeTwo though. It finds the first record that is ActionTypeOne or ActionTypeTwo.
I would suggest:
public Attrib DetermineAttribution(Data data)
{
var types = Enum.GetValues(typeof (Action)).Cast<Action>();
var merged = from c in data.actions
from t in types
where c.actionType == t
select new Attrib {id = c.id, name = c.name};
return merged.FirstOrDefault();
}
var one = from c in data.actions
where c.actionType == Action.ActionTypeOne
|| c.actionType == Action.ActionTypeTwo
orderby c.actionType == Action.ActionTypeOne ? 0 : 1
select new Attrib
{
id = c.id,
name = c.name
}).FirstOrDefault();
The equivalent SQL query would be ( I used a Case statement because I did not know the data type of the ActionType column):
Select TOP 1 id, name
From Actions
where ActionType In(ActionTypeOne, ActionTypeTwo)
Order By Case ActionType When 1 Then 0 Else 1 End ASC
加载中,请稍侯......
精彩评论