How return MULTIPLE results matching??
my method.. :
public IQueryable<Products> GetSelectProduct()
{
int[] value = GetProdutctsBascket();
return mm.getProducts().Where(p => p.Id.Equals(value));
}
how select widht array and return this ???
Try:
return mm.getProducts().Where(p => value.Contains(p.Id));
YD1m answered the question in exactly the correct way. However, I offer a small alternative - just because you can. You can use an extension method on you IEnumerable which serves the same purpose:
public static class MiscServiceTools
{
public static IEnumerable<T> WhereIn<T, TValue>(
this IQueryable<T> query,
Expression<Func<T, TValue>> selector,
params TValue[] collection) where T : class
{
if (selector == null) throw new ArgumentNullException("selector");
if (collection == null) throw new ArgumentNullException("collection");
ParameterExpression p = selector.Parameters.Single();
if (!collection.Any()) return query;
IEnumerable<Expression> equals = collection.Select(value =>
(Expression) Expression.Equal(selector.Body,
Expression.Constant(value, typeof (TValue))));
Expression body = equals.Aggregate(Expression.Or);
return query.Where(Expression.Lambda<Func<T, bool>>(body, p));
}
}
the usage would then be:
return mm.getProducts().WhereIn(p => p.Id, value);
Related
I'm trying to use the SQL function CONSTAINS to filter some data on QueryOver API.
The main issue is i can't use SqlFunction in where clause, it does not compile, because a ICriterion is needed.
var result = Session.QueryOver<Individual>()
.Where(Projections.SqlFunction(
"FullTextContains", NHibernateUtil.Boolean,
Projections.Property<Individual>(x => x.LastName),
Projections.Constant("something")))
.List();
I tried to match it to a TRUE constant, but when the query is executed it generates syntax error, because CONSTAINS function can't be used with equals operator.
var result = Session.QueryOver<Individual>()
.Where(Restrictions.Eq(Projections.SqlFunction(
"FullTextContains", NHibernateUtil.Boolean,
Projections.Property<Individual>(p => p.LastName),
Projections.Constant("something")), true))
.List();
How can i use a boolean sql function directly in where expression on QueryOver API?
This is my finding for letting QueryOver support it:
var projection = Projections.SqlFunction("FullTextContains",
NHibernateUtil.Boolean,
Projections.Property<Individual>(x => x.LastName),
Projections.Constant("something"));
var result = Session.QueryOver<Individual>()
.Where(new ProjectionAsCriterion(projection))
.List();
To use a IProjection as a ICriterion I created my own implementation based on SimpleExpression class from NHibernate project.
public class ProjectionAsCriterion : AbstractCriterion
{
private readonly IProjection _projection;
public ProjectionAsCriterion(IProjection projection)
{
_projection = projection;
}
public override SqlString ToSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery,
IDictionary<string, IFilter> enabledFilters)
{
var columnNames = CriterionUtil.GetColumnNamesForSimpleExpression(
null, _projection, criteriaQuery, criteria, enabledFilters, this, string.Empty);
var sqlBuilder = new SqlStringBuilder(4 * columnNames.Length);
for (int i = 0; i < columnNames.Length; i++)
{
if (i > 0)
{
sqlBuilder.Add(" and ");
}
sqlBuilder.Add(columnNames[i]);
}
return sqlBuilder.ToSqlString();
}
public override TypedValue[] GetTypedValues(ICriteria criteria, ICriteriaQuery criteriaQuery)
{
var typedValues = new List<TypedValue>();
if (_projection != null)
{
typedValues.AddRange(_projection.GetTypedValues(criteria, criteriaQuery));
}
typedValues.Add(GetParameterTypedValue(criteria, criteriaQuery));
return typedValues.ToArray();
}
private TypedValue GetParameterTypedValue(ICriteria criteria, ICriteriaQuery criteriaQuery)
{
return CriterionUtil.GetTypedValues(criteriaQuery, criteria, _projection, null).Single();
}
public override IProjection[] GetProjections()
{
return new[] { _projection };
}
public override string ToString()
{
return _projection.ToString();
}
}
I've seen this kind of thing described in various examples showing how to create a REST service which takes arrays or a list of objects as part of the URL.
My question is, how to implement this using RESTeasy?
Something like the following would be how i would assume this to work.
#GET
#Path("/stuff/")
#Produces("application/json")
public StuffResponse getStuffByThings(
#QueryParam("things") List<Thing> things);
Create a StringConverter and a use a wrapper object. Here is a quick and dirty example:
public class QueryParamAsListTest {
public static class Thing {
String value;
Thing(String value){ this.value = value; }
}
public static class ManyThings {
List<Thing> things = new ArrayList<Thing>();
ManyThings(String values){
for(String value : values.split(",")){
things.add(new Thing(value));
}
}
}
static class Converter implements StringConverter<ManyThings> {
public ManyThings fromString(String str) {
return new ManyThings(str);
}
public String toString(ManyThings value) {
//TODO: implement
return value.toString();
}
}
#Path("/")
public static class Service {
#GET
#Path("/stuff/")
public int getStuffByThings(
#QueryParam("things") ManyThings things){
return things.things.size();
}
}
#Test
public void test() throws Exception {
Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
dispatcher.getProviderFactory().addStringConverter(new Converter());
dispatcher.getRegistry().addSingletonResource(new Service());
MockHttpRequest request = MockHttpRequest.get("/stuff?things=a,b,c");
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
Assert.assertEquals("3", response.getContentAsString());
}
}
I think you can also use a StringParamUnmarshaller
I had some luck with this, using Collection rather than List. I was unable to make a StringConverter for List work.
#Provider
public class CollectionConverter implements StringConverter<Collection<String>> {
public Collection<String> fromString(String string) {
if (string == null) {
return Collections.emptyList();
}
return Arrays.asList(string.split(","));
}
public String toString(Collection<String> values) {
final StringBuilder sb = new StringBuilder();
boolean first = true;
for (String value : values) {
if (first) {
first = false;
} else {
sb.append(",");
}
sb.append(value);
}
return sb.toString();
}
}
I did the toString from my head. Be sure to write unit tests for it to verify. But of course, everything is easier and clearer when you use Guava. Can use Joiner and Splitter. Really handy.
Just use a wrapper on its own, no need for anything else.
In your endpoint
#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
#Path("/find")
#GET
MyResponse find(#QueryParam("ids") Wrapper ids);
And you wrapper looks like this :
public class Wrapper implements Serializable {
private List<BigInteger> ids = Collections.emptyList();
public String toString() {
return Joiner.on(",")
.join(ids);
}
public List<BigInteger> get() {
return ids;
}
public Wrapper(String s) {
if (s == null) {
ids = Collections.emptyList();
}
Iterable<String> splitted = Splitter.on(',')
.split(s);
Iterable<BigInteger> ids = Iterables.transform(splitted, Functionz.stringToBigInteger);
this.ids = Lists.newArrayList(ids);
}
public Wrapper(List<BigInteger> ids) {
this.ids = ids;
}
}
I have tried all variaions that I can find others using, and frankly they all seem to boil down to what I already have.
I want a generic system for invoking methods based on generic inputs. Not sure that really captures it fully, but not sure how to state it.
Here we go:
I want to make breadcrumbs from a params of Expression>
here, SelectedDivisions is ObservableCollection and ModelId is long?.
So, the point is that I want to feed in a list of varying properties, have them processed by the data class such that each is processed by the appropriate method inside of data
data.MakeBreadCrumbs(() => dc.SelectedDivisions, () => dc.ModelId);
data contains the following code:
public void MakeBreadCrumbs(params Expression<Func<object>>[] propertyExpressions) {
foreach (Expression<Func<object>> propertyExpression in propertyExpressions) {
MemberExpression member = propertyExpression.Body as MemberExpression;
if (member == null) {
UnaryExpression uExp = propertyExpression.Body as UnaryExpression;
member = uExp.Operand as MemberExpression;
}
PropertyInfo propInfo = member.Member as PropertyInfo;
Type[] propTypes = propInfo.PropertyType.GetGenericArguments();/
MethodInfo methodInfo = typeof(BreadcrumbData).GetGenericMethod("MakeBreadCrumb", new Type[] { propInfo.PropertyType, typeof(string) }); //
if (methodInfo.IsGenericMethod) {
methodInfo.MakeGenericMethod(propTypes[0]);
}
ConstantExpression ce = Expression.Constant(propertyExpression.Compile().Invoke());
string criterionName = ReadCriterionName(propertyExpression);
methodInfo.Invoke(this, new object[] { ce.Value, criterionName });
}
the last line fails with "Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true." when I am processing the property expression for the ObservableCollection item.
Here are the methods defined in the data class which are available, and which are correctly selected, but the one for the ObservableCollection fails on invocation
(LookupTypeBase is a class particular to my solution, but insert any type here that works with the type of a fake ObservableCollection property)
public void MakeBreadCrumb<T>(ObservableCollection<T> selections, string criterionName) where T : LookupTypeBase {...}
public void MakeBreadCrumb(long? value, string criterionName) {...}
public static class xxx {
public static MethodInfo GetGenericMethod(this Type type, string name, Type[] parameterTypes) {
var methods = type.GetMethods();
foreach (var method in methods.Where(m => m.Name == name)) {
var methodParameterTypes = method.GetParameters().Select(p => p.ParameterType).ToArray();
if (methodParameterTypes.SequenceEqual(parameterTypes, new SimpleTypeComparer())) {
return method;
}
}
return null;
}
private class SimpleTypeComparer : IEqualityComparer<Type> {
public bool Equals(Type x, Type y) {
return x.Assembly == y.Assembly && x.Namespace == y.Namespace && x.Name == y.Name;
}
public int GetHashCode(Type obj) {
throw new NotImplementedException();
}
}
}
It's silverlight 4 so you have latebound method invocation with the dynamic keyword, which should make this easy and fast:
BreadcrumbData.MakeBreadCrumb((dynamic)ce.Value, (dynamic)criterionName);
Aside from that i think your issue is that MakeGenericMethod returns a new methodinfo which you ignore instead of keeping around like so:
if (methodInfo.IsGenericMethod) {
methodInfo = methodInfo.MakeGenericMethod(propTypes[0]);
}
I've seen answers mentioning something compact like this:here
List<T> withDupes = LoadSomeData();
List<T> noDupes = withDupes.Distinct().ToList();
So I tried the following (syntax)
List<InfoControl> withDupes = (List<InfoControl>)listBox1.ItemsSource;
listBox1.ItemsSource = withDupes.Distinct().ToList();
but withDupes is null ? Perhaps I am retrieving the wrong data list. I added InfoControls one at a time.
Is there something else I should be implementing in InfoControl class? (Equal,hashCode)?
Thanks
Addendum 1: [ignore I should not be translating from Java :) ]
Also have (translated from a Java example, not sure it's 100% correct) declared in the InfoControl class..
public Boolean Equals(Object obj)
{ if (obj == this) { return true; }
if (!(obj is InfoControl)) { return false; }
InfoControl other = (InfoControl)obj;
return this.URL.Equals(other.URL); }
public int hashCode()
{ return this.URLFld.Content.GetHashCode(); }
Addendum 2:
When I try to use override based on the msdn link custom type example it says it is sealed :)
It does not seem distinct is stepping thru GetHashCode() and I am still getting the same listbox.items.count after distinct.
bool IEquatable<InfoControl>.Equals(InfoControl other)
{
if (Object.ReferenceEquals(other, null)) return false;
if (Object.ReferenceEquals(this, other)) return true;
return URL.Equals(other.URL);
}
public int GetHashCode(InfoControl obj)
{
return obj.URL.GetHashCode();
}
Addendum 3:
When I try override VS2010 says it is sealed? "cannot override inherited member 'System.Windows.DependencyObject.GetHashCode()' because it is sealed" what am I doing wrong?
public override int GetHashCode()
{
return URL.GetHashCode();
}
public string URL
{
get { return this.URLFld.Content.ToString() ; }
set
{
this.URLFld.Content = value;
}
}
.
Addendum 4:
public partial class InfoControl : UserControl
, IEquatable<YouTubeInfoControl>
{
private string URL_;
public string URL
{
get { return URL_; }
set
{
URL_ = value;
}
}
bool IEquatable<YouTubeInfoControl>.Equals(YouTubeInfoControl other)
{
if (Object.ReferenceEquals(other, null)) return false;
if (Object.ReferenceEquals(this, other)) return true;
return URL == other.URL;
}
public override int GetHashCode()
{
return URL.GetHashCode();
}
}
A ListBox's items can either be set via ListBox.Items or ListBox.ItemsSource, if you add items using listBox1.Items.Add this does not affect the ItemsSource which will stay null. In this case you should get your initial list from listBox1.Items.
If you're adding the InfoControl objects one at a time, the ItemSource of the listBox will remain set to NULL. You're better off binding a List to the listbox which will allow you to get the data back off of the ItemSource property later
Here's the scenario:
Silverlight 4.0, DataGrid, PagedCollectionView itemssource.
The objective is to apply a Filter to the PCV. The filter needs to be a Predicate<object>(Method) - where Method implements some logic against the object and returns true/false for inclusion.
What I have is a need to optionally include 3 different criteria in the filter logic and explicit code quickly gets ugly. We don't want that, do we?
So I see that there is a way to build an expression tree using PredicateBuilder and pass that into Linq.Where, a la:
IQueryable<Product> SearchProducts (params string[] keywords)
{
var predicate = PredicateBuilder.False<Product>();
foreach (string keyword in keywords)
{
string temp = keyword;
predicate = predicate.Or (p => p.Description.Contains (temp));
}
return dataContext.Products.Where (predicate);
}
[this is not what I'm trying to do by the way]
With 3 optional criteria, I want to write something like:
Ratings.Filter = BuildFilterPredicate(); // Ratings = the PagedCollectionView
private Predicate<object> BuildFilterPredicate()
{
bool FilterOnOrder = !String.IsNullOrEmpty(sOrderNumberFilter);
var predicate = PredicateBuilder.False<object>();
if (ViewMineOnly)
{
predicate = predicate.And(Rating r => sUserNameFilter == r.Assigned_To);
}
if (ViewStarOnly)
{
predicate = predicate.And(Rating r => r.Star.HasValue && r.Star.Value > 0);
}
if (FilterOnOrder)
{
predicate = predicate.And(Rating r => r.ShipmentInvoice.StartsWith(sOrderNumberFilter));
}
return predicate;
}
Of course this won't compile because PredicateBuilder creates an Expression<Func<T, bool>> not an actual predicate method. But I see that there are ways to convert an expression tree into a method so it seemed to me there ought to be a way to accomplish what I'm after without resorting to a bunch of nested if/then/else statements.
So the question is - is there a way to build a predicate method dynamically?
TIA
to do this for a PagedCollectionView, you need to have a Predicate. So it looks like:
private Predicate<object> ConvertExpressionToPredicate(Expression<Func<object, bool>> exp)
{
Func<object, bool> func = exp.Compile();
Predicate<object> predicate = new Predicate<object>(func);
//Predicate<object> predicate = t => func(t); // also works
//Predicate<object> predicate = func.Invoke; // also works
return predicate;
}
and build the expression:
private Expression<Func<object, bool>> BuildFilterExpression()
{
...snip...
var predicate = PredicateBuilder.True<object>();
if (ViewMineOnly)
{
predicate = predicate.And(r => ((Rating)r).Assigned_To.Trim().ToUpper() == sUserNameFilter || ((Rating)r).Assigned_To.Trim().ToUpper() == "UNCLAIMED");
}
if (ViewStarOnly)
{
predicate = predicate.And(r => ((Rating)r).Star.HasValue && ((Rating)r).Star.Value > 0);
}
if (FilterOnOrder)
{
predicate = predicate.And(r => ((Rating)r).ShipmentInvoice.Trim().ToUpper().StartsWith(sOrderNumberFilter));
}
if (ViewDueOnly)
{
predicate = predicate.And(r => ((Rating)r).SettlementDueDate <= ThisThursday);
}
return predicate;
}
and then set the filter:
Ratings.Filter = ConvertExpressionToPredicate(BuildFilterExpression());
I faced the same problem. I had 3 criteria.
What I did is the following :
One method to validate each criteria
One method to validate the object
The code looked quite clean and it was easy to maintain.
Ratings.Filter = new predicate<objects>(validateObject);
private bool validateObject(object o)
{
return validateFirstCriteria(o) &&
validateSecondCriteria(o) &&
validateThirdCriteria(o);
}
private bool validateFirstObject(object o)
{
if (ViewMineOnly)
{
Rating r = o as Rating;
if (o != null)
{
return (r.Star.HasValue && r.Star.Value > 0);
}
}
return false;
}
private bool validateSecondObject(object o)
{
if (ViewStarOnly)
{
Rating r = o as Rating;
if (o != null)
{
return sUserNameFilter == r.Assigned_To;
}
}
return false;
}
private bool validateThirdObject(object o)
{
if (FilterOnOrder)
{
Rating r = o as Rating;
if (o != null)
{
return r.ShipmentInvoice.StartsWith(sOrderNumberFilter);
}
}
return false;
}
EDIT
If you want to stuck to Expression trees. You could take a look here : http://msdn.microsoft.com/en-us/library/bb882536.aspx
You can convert the expression tree to a lambda expression and then compile the lambda expression. After then you can use it as a method. Exemple :
// The expression tree to execute.
BinaryExpression be = Expression.Power(Expression.Constant(2D), Expression.Constant(3D));
// Create a lambda expression.
Expression<Func<double>> le = Expression.Lambda<Func<double>>(be);
// Compile the lambda expression.
Func<double> compiledExpression = le.Compile();
// Execute the lambda expression.
double result = compiledExpression();
// Display the result.
Console.WriteLine(result);
// This code produces the following output:
// 8
Thanks to Benjamin's hints and this post -> How to convert Func<T, bool> to Predicate<T>?
I figured it out.
The essence is:
private static Predicate<T> ConvertExpressionToPredicate(Expression<Func<T, bool>> exp)
{
Func<T, bool> func = exp.Compile();
Predicate<T> predicate = new Predicate<T>(func);
//Predicate<T> predicate = t => func(t); // also works
//Predicate<T> predicate = func.Invoke; // also works
return predicate;
}
This will compile the expression tree to a single function and return a predicate to call the function.In use, it looks like:
private static bool ViewStarOnly;
private static bool LongNameOnly;
static void Main(string[] args)
{
List<Dabble> data = GetSomeStuff();
ViewStarOnly = true;
LongNameOnly = true;
Expression<Func<Dabble, bool>> exp = BuildFilterExpression();
List<Dabble> filtered = data.FindAll(ConvertExpressionToPredicate(exp));
PrintSomeStuff(filtered);
}
private static Predicate<Dabble> ConvertExpressionToPredicate(Expression<Func<Dabble, bool>> exp)
{
Func<Dabble, bool> func = exp.Compile();
Predicate<Dabble> predicate = new Predicate<Dabble>(func);
//Predicate<Dabble> predicate = t => func(t); // also works
//Predicate<Dabble> predicate = func.Invoke; // also works
return predicate;
}
private static Expression<Func<Dabble, bool>> BuildFilterExpression()
{
var predicate = PredicateBuilder.True<Dabble>();
if (ViewStarOnly)
{
predicate = predicate.And(r => r.Star.HasValue && r.Star.Value > 0);
}
if (LongNameOnly)
{
predicate = predicate.And(r => r.Name.Length > 3);
}
return predicate;
}
Thanks!