How to build dynamic LINQ to SharePoint expression like this(but store "Bill", "Sam" in array):
// listing 1
// SPEntityModelDataContext generated with SPMetal
using (var db = new SPEntityModelDataContext("http://sharepoint/"))
{
var res = db.OrgUnitToUser
.Where(oo => oo.User.Title == "Bill" || oo.User.Title == "Sam")
.ToList();
}
we try to use PredicateBuilder
This don't work:
// listing 2
using (var db = new SPEntityModelDataContext("http://sharepoint/"))
{
var names = new String[] {"Bill", "Sam" };
var inner = PredicateBuilder.False<OrgUnitToUserItem>();
foreach (var name in names)
{
var temp = name;
inner = inner.Or(pp => pp.User.Title == temp); // use projection
}
var res = db.OrgUnitToUser
.Where(inner)
.ToList(); // ERROR
}
Error: The query uses unsupported elements, such as references to more than one list, or the projection of a complete entity by using EntityRef/EntitySet.
For example this code work
// listing 3
var inner = PredicateBuilder.False<OrgUnitToUserItem>();
foreach (var name in names)
{
var temp = name;
inner = inner.Or(pp => pp.Title == temp); // without projection
}
var res = db.OrgUnitToUser
.Where(inner)
.ToList();
It is posible to use Compile():
// listing 4
using (var db = new SPEntityModelDataContext("http://sharepoint/"))
{
var names = new String[] {"Bill", "Sam" };
var inner = PredicateBuilder.False<OrgUnitToUserItem>();
foreach (var name in names)
{
var temp = name;
inner = inner.Or(pp => pp.User.Title == temp); // use projection
}
var res = db.OrgUnitToUser
.Where(inner.Compile())
.ToList();
}
No error, but listing 4 use Linq To Object - first get all User and iterate them. CAML not the same as in listing 1.
For example: .Where(BuildOrExpressionContains(tt => tt.User.Title, names) || tt.Id == 2)
– Alex Feb 21 '12 at 22:32