How to implement “NOT IN” clause with Dapper Extensions Predicate? - dapper

I found how to implement IN clause using Dapper Extensions here.
Now, I want to implement NOT IN clause.
So, I am expecting SQL query something like below:
SELECT * FROM MyTable
WHERE MyField NOT IN (param1, param2)
But I could not find anything about NOT IN or NOT clause in Dapper Extensions.
How can I implement NOT IN clause with Dapper Extensions Predicate?

Please refer to this answer (linked in question as well) to understand how to implement IN clause.
To turn the IN clause as mentioned above to NOT IN clause, use the last bool not parameter.
This is optional parameter and default value for it is false.
That is why; even though so obvious, it is bit hidden and hence undiscovered.
Documentation does not mention it explicitly either.
Below are the definitions of each predicate defined in Dapper Extensions source code:
public static class Predicates
{
public static IBetweenPredicate Between<T>(Expression<Func<T, object>> expression, BetweenValues values, bool not = false) where T : class;
public static IExistsPredicate Exists<TSub>(IPredicate predicate, bool not = false) where TSub : class;
public static IFieldPredicate Field<T>(Expression<Func<T, object>> expression, Operator op, object value, bool not = false) where T : class;
public static IPropertyPredicate Property<T, T2>(Expression<Func<T, object>> expression, Operator op, Expression<Func<T2, object>> expression2, bool not = false)
where T : class
where T2 : class;
}
Sample code is as below:
var predicate = Predicates.Field<Customer>
(f => f.CustomerID, Operator.Eq, listOfIDs, true);
Observe the value true for last parameter in above code. The listOfIDs is an IEnumerable of your data type.
Please refer to this for more source code.

Related

iBatis unable to read property from Map when using isEqual

I'm seeing a very bizarre issue with iBatis when trying to read a property from a Java map using isEqual, but not with other iBatis operators. For example it is able to read the map properties fine when using isNotNull and iterate. The xml:
<isNotNull property="filterCriteria.account">
AND
id
<isEqual property="filterCriteria.account.meetsCriteria" compareValue="false">
NOT
</isEqual>
IN
(SELECT DISTINCT id
FROM account
WHERE some other criteria....
)
</isNotNull>
The 2 java classes we're using here:
public class SearchProfile {
private Map<String, SearchProfileCriteria> filterCriteria;
public SAOSearchProfile() {
filterCriteria = new HashMap<>();
}
public Map<String, SAOSearchProfileCriteria> getFilterCriteria() {
return filterCriteria;
}
public void setFilterCriteria(Map<String, SAOSearchProfileCriteriaBase> filterCriteria) {
this.filterCriteria = filterCriteria;
}
}
Above is the container object that is passed to iBatis for the querying, and below is the criteria object that will be the value of the map. In this example it is keyed with the String "account"
public class SearchProfileCriteria {
boolean meetsCriteria;
public String getCriteriaAsString() {
return StringUtils.getStringValueFromBoolean(meetsCriteria);
}
public boolean isMeetsCriteria() {
return meetsCriteria;
}
public void setMeetsCriteria(boolean meetsCriteria) {
this.meetsCriteria = meetsCriteria;
}
public String getSQLString(){
return meetsCriteria ? "" : "NOT";
}
}
And the exception:
Cause: com.ibatis.common.beans.ProbeException: There is no READABLE property named 'account' in class 'java.util.Map'; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:
The getSQLString() method was my half baked attempt at a work around, the String gets escaped in the query and throws a syntax error.
When I remove the <isEqual> block the query executes find, which indicates it is able to read the "account" key when checking the to see if it is null. As I mentioned above, we're also able to use the map keys in <iterate> tags without issue. It seems <isEqual> and <isNotEqual> are the only tags causing issues. Does anyone have experience with this or know what may be going on?
Beware: Using isNotNull, isEqual, iterate is iBatis, they don't exist anymore in Mybatis, so referencing to Mybatis indifferently is confusing.
Reference documentation.
For your issue, how does it behave if replacing Map with a class (property will be known at compile time)?
Or try using <isPropertyAvailable>.
The work around could work with right syntax: $ instead of #: $filterCriteria.account.SQLString$ instead of #filterCriteria.account.SQLString#, then the value is just concatenated instead of bound as parameter.

How to define nullable types if nested types are not supported

I'm using a component and one of the properties is of type System.Type. This works fine in most cases but now I find myself in need of int?. This didn't seem quite straightforward and after some searching and trial and error I ended up with this:
<local:NullableUInt32PropertyEditor PropertyType="{x:Type system:Nullable`1[System.UInt32]}"/>
This compiles and works as it should but the Error list gives
Nested types are not supported: Nullable`1[System.UInt32].
Intellisense also give a squigly line under the statement and the preview also states invallid markup.
What is the correct way to handle this?
thank you,
Jef
Edit: this is not the same as declaring a value as in this question (Declare a Nullable int (int?) using XAML). I need to declare the type, not a value.
After some further research I came up with this solution:
public class NullableExtension : TypeExtension
{
public NullableExtension()
{
}
public NullableExtension(string type)
: base(type)
{
}
public NullableExtension(Type type)
: base(type)
{
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
Type basis = (Type)base.ProvideValue(serviceProvider);
return typeof(Nullable<>).MakeGenericType(basis);
}
}
and then in xaml:
<local:NullableUInt32PropertyEditor PropertyType="{local:Nullable system:UInt32}"/>

Can I develop an SQL/CLR function that can accept arguments of any type like MAX()?

For example, can I develop MAX() function using C# by myself? Thanks!
As stated in this post (http://stackoverflow.com/questions/4749071/clr-table-valued-function-with-array-argument?rq=1), table-valued parameters are not supported. SQL/CLR functions take arguments of types in the namespace System.Data.SqlTypes - such as SqlChars, SqlString, SqlInt32, etc. Basically, they are primitive types: no rowsets, no arrays allowed as function parameters (the answer in the previous link proposes work-arounds).
SQL/CLR functions are better suited for things like leveraging the System.Text.RegularExpressions namespace (Regex.Match), or for creating a function that returns a hash of a given value - a password string, perhaps.
Here's an example of SQL functions in a CLR assembly:
public static partial class UserDefinedFunctions
{
public static readonly RegexOptions Options = RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline;
[SqlFunction]
public static SqlBoolean RegexMatch(SqlChars input, SqlString pattern)
{
Regex regex = new Regex(pattern.Value, Options);
return regex.IsMatch(new string(input.Value));
}
[SqlFunction]
public static SqlChars RegexGroup(SqlChars input, SqlString pattern, SqlString name)
{
Regex regex = new Regex(pattern.Value, Options);
Match match = regex.Match(new string(input.Value));
return match.Success ? new SqlChars(match.Groups[name.Value].Value) : SqlChars.Null;
}
}
(taken from http://msdn.microsoft.com/en-us/magazine/cc163473.aspx)

How to use predicate search with Linq-to-SQL

We are using Linq-to-SQL with SQL Server as an ORM on our new project. I have never used Linq-to-SQL before, so my question can be a bit dumb. I want to have a method that will perform a search for entities in DB by predicate, something like this:
public IEnumerable<T> Get<T>(Expression<Func<T, bool>> #where)
Could you give some advices where I can see some code samples or ideas how to implement this?
You want Where (here, originalList is any enumerable, in particular it can be a table from your context):
var filteredList = originalList.Where(element => ShouldBeIncluded(element));
Edit:
or
var filteredList =
from element in originalList
where ShouldBeIncluded(element)
select element;
And if ShouldBeIncluded is a Func<T, bool>, there's an eye-candy simplified syntax:
var filteredList = originalList.Where(ShouldBeIncluded);
Edit 2: also, note that the complete syntax is:
var filteredList = originalList.Where<TTypeOfElement>(element => ShouldBeIncluded(element));
But the generic argument can be omitted since the compiler will deduce it from the type of originalList (supposing it is an IEnumerable<TTypeOfelement>).

App Engine - Query using a class member as parameter

I have a simple class, relevant details below:
#PersistenceCapable(identityType = IdentityType.APPLICATION)
public class SimpleCategory implements Serializable{
...
public static enum type{
Course,
Category,
Cuisine
}
#Persistent
public type t;
...
}
I am attempting to query all SimpleCategory objects of the same type.
public SimpleCategory[] getCategories(SimpleCategory.type type) {
PersistenceManager pm = PMF.get().getPersistenceManager();
try{
Query q = pm.newQuery(SimpleCategory.class);
q.setFilter("t == categoryType");
q.declareParameters("SimpleCategory.type categoryType");
List<SimpleCategory> cats = (List<SimpleCategory>) q.execute(type);
...
}
This results in a ClassNotResolvedException for SimpleCategory.type. The google hits I've found so far recommended to:
Use query.declareImports to specify the class i.e. q.declareImports("com.test.zach.SimpleCategory.type");
Specify the fully qualified name of SimpleCategory in declareParameters
Neither of these suggestions has worked. By removing .type and recompiling, I can verify that declareParameters can see SimpleCategory just fine, it simply cannot see the SimpleCategory.type, despite the fact that the remainder of the method has full visibility to it.
What am I missing?
You elided (...) whether public static enum type itself is declared #PersistenceCapable. If it isn't, that might explain why the query parser isn't able to resolve a reference to the type class.
Something that has seemed to work for me is writing the query string using an implicit parameter and not using the declareParameters() method.
q.setFilter("t == :categoryType");
List<SimpleCategory> cats = (List<SimpleCategory>) q.execute(type)

Resources