public IQueryOver <NodeVersion, NodeVersionStatusHistory> GenerateVersionedQueryPlusAttributes(Guid[] nodeIds = null, RevisionStatusType revisionStatus = null, bool limitToLatestRevision = true, IEnumerable <SortClause> sortClauses = null) { if (sortClauses == null) { sortClauses = Enumerable.Empty <SortClause>(); } NodeVersion outerVersionSelect = null; var outerQuery = GenerateVersionedQuery(out outerVersionSelect, nodeIds, revisionStatus, limitToLatestRevision); Attribute attribAlias = null; AttributeDateValue attributeDateValue = null; AttributeDecimalValue attributeDecimalValue = null; AttributeIntegerValue attributeIntegerValue = null; AttributeStringValue attributeStringValue = null; AttributeLongStringValue attributeLongStringValue = null; outerQuery = outerQuery .Left.JoinAlias(() => outerVersionSelect.Attributes, () => attribAlias) // Using a left join identifies to Nh that it can reuse the loaded Attributes because Nh considers them to be unaffected by the query, otherwise it issues another select from accessing NodeVersion.Attributes .Left.JoinAlias(() => attribAlias.AttributeStringValues, () => attributeStringValue) .Left.JoinAlias(() => attribAlias.AttributeLongStringValues, () => attributeLongStringValue) .Left.JoinAlias(() => attribAlias.AttributeIntegerValues, () => attributeIntegerValue) .Left.JoinAlias(() => attribAlias.AttributeDecimalValues, () => attributeDecimalValue) .Left.JoinAlias(() => attribAlias.AttributeDateValues, () => attributeDateValue); //if (sortClauses.Any()) //{ // AttributeDefinition attribDef = null; // outerQuery = outerQuery.JoinAlias(() => attribAlias.AttributeDefinition, () => attribDef); // foreach (var sortClause in sortClauses) // { // var coalesce = Projections.SqlFunction("coalesce", NHibernateUtil.String, // Projections.Property(() => attributeStringValue.Value), // Projections.Property(() => attributeLongStringValue.Value)); // if (sortClause.Direction == SortDirection.Ascending) // outerQuery = outerQuery.OrderBy(coalesce).Asc; // else // outerQuery = outerQuery.OrderBy(coalesce).Desc; // } //} return(outerQuery); }
public override QueryOver <NodeVersion> VisitFieldPredicate(FieldPredicateExpression node) { var fieldName = node.SelectorExpression.FieldName; var valueKey = node.SelectorExpression.ValueKey; var fieldValue = node.ValueExpression.Value; var fieldValueType = fieldValue != null?fieldValue.GetType() : typeof(string); switch (fieldName.ToLowerInvariant()) { case "id": Guid idValue = GetIdValue(node); switch (node.ValueExpression.ClauseType) { case ValuePredicateType.Equal: return(QueryOver.Of <NodeVersion>().Where(x => x.Node.Id == idValue).Select(x => x.Id)); case ValuePredicateType.NotEqual: return(QueryOver.Of <NodeVersion>().Where(x => x.Node.Id != idValue).Select(x => x.Id));; default: throw new InvalidOperationException( "Cannot query an item by id by any other operator than == or !="); } } // First look up the types of the main field AttributeDefinition defAlias = null; AttributeType typeAlias = null; var attributeType = _activeSession.QueryOver <AttributeDefinition>(() => defAlias) .JoinAlias(() => defAlias.AttributeType, () => typeAlias) .Where(() => defAlias.Alias == fieldName) .Select(x => typeAlias.PersistenceTypeProvider) .List <string>(); var typesAlreadyEstablished = new List <string>(); var typesToQuery = new List <DataSerializationTypes>(); foreach (var type in attributeType) { var typeName = type; if (typesAlreadyEstablished.Contains(typeName)) { continue; } try { typesAlreadyEstablished.Add(typeName); var persisterType = Type.GetType(typeName, false); if (persisterType != null) { var persisterInstance = Activator.CreateInstance(persisterType) as IAttributeSerializationDefinition; if (persisterInstance != null) { typesToQuery.Add(persisterInstance.DataSerializationType); } } } catch (Exception) { throw; } } // U5-789 // Workaround pending a better check of what data is actually saved // An issue arose because previous data had been saved in long-string, // but the datatype changed to be just string, therefore only string was // being queried despite all the data residing still in long-string if (typesToQuery.Contains(DataSerializationTypes.String) && !typesToQuery.Contains(DataSerializationTypes.LongString)) { typesToQuery.Add(DataSerializationTypes.LongString); } NodeVersion aliasNodeVersion = null; Attribute aliasAttribute = null; AttributeDefinition aliasAttributeDefinition = null; AttributeStringValue aliasStringValue = null; AttributeLongStringValue aliasLongStringValue = null; AttributeIntegerValue aliasIntegerValue = null; AttributeDecimalValue aliasDecimalValue = null; NodeRelation aliasNodeRelation = null; AttributeDateValue aliasDateValue = null; QueryOver <NodeVersion, AttributeDefinition> queryExtender = QueryOver.Of <NodeVersion>(() => aliasNodeVersion) .JoinQueryOver <Attribute>(() => aliasNodeVersion.Attributes, () => aliasAttribute) .JoinQueryOver <AttributeDefinition>(() => aliasAttribute.AttributeDefinition, () => aliasAttributeDefinition); int numberOfMatchesEvaluated = 0; AbstractCriterion restrictionBuilder = null; foreach (var dataSerializationTypese in typesToQuery.Distinct()) { AbstractCriterion restriction = null; Expression <Func <object> > propertyExpression = null; Expression <Func <object> > subkeyExpression = null; List <ValuePredicateType> validClauseTypes = null; var useLikeMatchForStrings = false; switch (dataSerializationTypese) { case DataSerializationTypes.SmallInt: case DataSerializationTypes.LargeInt: case DataSerializationTypes.Boolean: queryExtender = queryExtender.Left.JoinAlias(() => aliasAttribute.AttributeIntegerValues, () => aliasIntegerValue); propertyExpression = () => aliasIntegerValue.Value; subkeyExpression = () => aliasIntegerValue.ValueKey; validClauseTypes = new List <ValuePredicateType>() { ValuePredicateType.Equal, ValuePredicateType.GreaterThan, ValuePredicateType.GreaterThanOrEqual, ValuePredicateType.LessThan, ValuePredicateType.LessThanOrEqual, ValuePredicateType.NotEqual }; break; case DataSerializationTypes.Decimal: queryExtender = queryExtender.Left.JoinAlias(() => aliasAttribute.AttributeDecimalValues, () => aliasDecimalValue); propertyExpression = () => aliasDecimalValue.Value; subkeyExpression = () => aliasDecimalValue.ValueKey; validClauseTypes = new List <ValuePredicateType>() { ValuePredicateType.Equal, ValuePredicateType.GreaterThan, ValuePredicateType.GreaterThanOrEqual, ValuePredicateType.LessThan, ValuePredicateType.LessThanOrEqual, ValuePredicateType.NotEqual }; break; case DataSerializationTypes.String: queryExtender = queryExtender.Left.JoinAlias(() => aliasAttribute.AttributeStringValues, () => aliasStringValue); propertyExpression = () => aliasStringValue.Value; subkeyExpression = () => aliasStringValue.ValueKey; validClauseTypes = new List <ValuePredicateType>() { ValuePredicateType.Equal, ValuePredicateType.NotEqual, ValuePredicateType.Contains, ValuePredicateType.StartsWith, ValuePredicateType.EndsWith, ValuePredicateType.MatchesWildcard }; break; case DataSerializationTypes.LongString: queryExtender = queryExtender.Left.JoinAlias(() => aliasAttribute.AttributeLongStringValues, () => aliasLongStringValue); propertyExpression = () => aliasLongStringValue.Value; subkeyExpression = () => aliasLongStringValue.ValueKey; useLikeMatchForStrings = true; validClauseTypes = new List <ValuePredicateType>() { ValuePredicateType.Equal, ValuePredicateType.NotEqual, ValuePredicateType.Contains, ValuePredicateType.StartsWith, ValuePredicateType.EndsWith, ValuePredicateType.MatchesWildcard }; break; case DataSerializationTypes.Date: queryExtender = queryExtender.Left.JoinAlias(() => aliasAttribute.AttributeDateValues, () => aliasDateValue); propertyExpression = () => aliasDateValue.Value; subkeyExpression = () => aliasDateValue.ValueKey; validClauseTypes = new List <ValuePredicateType>() { ValuePredicateType.Equal, ValuePredicateType.GreaterThan, ValuePredicateType.GreaterThanOrEqual, ValuePredicateType.LessThan, ValuePredicateType.LessThanOrEqual, ValuePredicateType.NotEqual, ValuePredicateType.Empty }; break; } if (!validClauseTypes.Contains(node.ValueExpression.ClauseType)) { throw new InvalidOperationException("A field of type {0} cannot be queried with operator {1}".InvariantFormat(dataSerializationTypese.ToString(), node.ValueExpression.ClauseType.ToString())); } switch (node.ValueExpression.ClauseType) { case ValuePredicateType.Equal: restriction = GetRestrictionEq(fieldValue, useLikeMatchForStrings, propertyExpression, subkeyExpression, valueKey); break; case ValuePredicateType.NotEqual: restriction = !GetRestrictionEq(fieldValue, useLikeMatchForStrings, propertyExpression); break; case ValuePredicateType.LessThan: restriction = GetRestrictionLt(fieldValue, propertyExpression); break; case ValuePredicateType.LessThanOrEqual: restriction = GetRestrictionLtEq(fieldValue, propertyExpression); break; case ValuePredicateType.GreaterThan: restriction = GetRestrictionGt(fieldValue, propertyExpression); break; case ValuePredicateType.GreaterThanOrEqual: restriction = GetRestrictionGtEq(fieldValue, propertyExpression); break; case ValuePredicateType.Contains: restriction = GetRestrictionContains(fieldValue, propertyExpression); break; case ValuePredicateType.StartsWith: restriction = GetRestrictionStarts(fieldValue, propertyExpression); break; case ValuePredicateType.EndsWith: restriction = GetRestrictionEnds(fieldValue, propertyExpression); break; } if (restriction != null) { if (numberOfMatchesEvaluated == 0) { restrictionBuilder = restriction; numberOfMatchesEvaluated++; } else { restrictionBuilder = Restrictions.Or(restriction, restrictionBuilder); } } } if (restrictionBuilder != null) { queryExtender = queryExtender.Where(restrictionBuilder); } queryExtender = queryExtender .And(x => aliasAttributeDefinition.Alias == fieldName); return(queryExtender.Select(x => x.Id)); }
public override FieldFilterResult VisitFieldPredicate(FieldPredicateExpression node) { var fieldName = node.SelectorExpression.FieldName; var valueKey = node.SelectorExpression.ValueKey; var fieldValue = node.ValueExpression.Value; var fieldValueType = fieldValue != null?fieldValue.GetType() : typeof(string); var toReturn = new FieldFilterResult(); RdbmsModel.Attribute att = null; Node outerNode = null; AttributeStringValue stringVal = null; AttributeLongStringValue longStrVal = null; AttributeIntegerValue integerVal = null; AttributeDecimalValue decimalVal = null; AttributeDateValue dateVal = null; AttributeDefinition def = null; // First check for special cases, typically stuff that can be queried // that isn't necessarily a value in any of the Attribute*Value tables switch (fieldName.ToLowerInvariant()) { case "utccreated": DateTimeOffset createdDtoValue = ParseDateTimeOffset(fieldValue); if (createdDtoValue == default(DateTime)) { break; } toReturn.NhCriterion = CreateRestriction(node.ValueExpression.ClauseType, () => outerNode.DateCreated, createdDtoValue); if (toReturn.NhCriterion != null) { toReturn.Joins.Add(new Join(() => agg.Node, () => outerNode, JoinType.InnerJoin)); } break; case "utcmodified": DateTimeOffset modifiedDtoValue = ParseDateTimeOffset(fieldValue); if (modifiedDtoValue == default(DateTime)) { break; } toReturn.NhCriterion = CreateRestriction(node.ValueExpression.ClauseType, () => agg.StatusDate, modifiedDtoValue); break; case "id": Guid idValue = GetIdValue(node); switch (node.ValueExpression.ClauseType) { case ValuePredicateType.Equal: toReturn.NhCriterion = Restrictions.Eq(Projections.Property(() => agg.Node.Id), idValue); break; case ValuePredicateType.NotEqual: toReturn.NhCriterion = !Restrictions.Eq(Projections.Property(() => agg.Node.Id), idValue); break; default: throw new InvalidOperationException("Cannot query an item by id by any other operator than == or !="); } break; case "system-internal-selected-template": //TODO Pending property editors getting involved in query modification prior to being passed to hive provider, //manually check for queries against a template here if (valueKey == "TemplateId" && fieldValue != null) { var tryParseResult = HiveId.TryParse(fieldValue.ToString()); if (!tryParseResult.Success || tryParseResult.Result.ProviderGroupRoot == null || tryParseResult.Result.ProviderId == null || (tryParseResult.Result.ProviderGroupRoot.AbsoluteUri != "storage://" && tryParseResult.Result.ProviderId != "templates")) { var normalisedFieldValue = "/" + fieldValue.ToString().TrimStart("/").TrimEnd(".") + "."; // Need to convert the value into the serialized form that a HiveId would use var newValue = new HiveId("storage", "templates", new HiveIdValue(normalisedFieldValue)).ToString(HiveIdFormatStyle.UriSafe); fieldValue = newValue; } else { fieldValue = tryParseResult.Result.ToString(HiveIdFormatStyle.UriSafe); } } break; } if (toReturn.NhCriterion != null) { // The special-case handling above has already set the criterion, // so we don't have to evaluate field values in this pass and can return return(toReturn); } // Establish which Attribute*Value tables to query // First look up the types of the main field AttributeDefinition defAlias = null; AttributeType typeAlias = null; var attributeType = _activeSession.NhSession.QueryOver <AttributeDefinition>(() => defAlias) .JoinAlias(() => defAlias.AttributeType, () => typeAlias) .Where(() => defAlias.Alias == fieldName) .Select(Projections.Distinct(Projections.Property(() => typeAlias.PersistenceTypeProvider))) .Cacheable() .List <string>(); foreach (var type in attributeType) { var typeName = type; // Ensure we don't do unneccessary calls to Activator.CreateInstance, // (_typesAlreadyEstablished lives for the lifetime of the visitor) // but still make sure we populate the toReturn.ValueTypesToQuery for this // visit to a field predicate if (TypesAlreadyDiscovered.ContainsKey(typeName)) { var dst = TypesAlreadyDiscovered[typeName]; if (toReturn.ValueTypesToQuery.Contains(dst)) { continue; } toReturn.ValueTypesToQuery.Add(dst); } try { var persisterType = Type.GetType(typeName, false); if (persisterType != null) { var persisterInstance = Activator.CreateInstance(persisterType) as IAttributeSerializationDefinition; if (persisterInstance != null && !toReturn.ValueTypesToQuery.Contains(persisterInstance.DataSerializationType)) { toReturn.ValueTypesToQuery.Add(persisterInstance.DataSerializationType); TypesAlreadyDiscovered.TryAdd(typeName, persisterInstance.DataSerializationType); } } } catch (Exception ex) { LogHelper.Error <NhCriteriaVisitor>("Error while trying to decide which value-tables to join & query", ex); throw; } } // U5-789 // Workaround pending a better check of what data is actually saved // An issue arose because previous data had been saved in long-string, // but the datatype changed to be just string, therefore only string was // being queried despite all the data residing still in long-string if (toReturn.ValueTypesToQuery.Contains(DataSerializationTypes.String) && !toReturn.ValueTypesToQuery.Contains(DataSerializationTypes.LongString)) { toReturn.ValueTypesToQuery.Add(DataSerializationTypes.LongString); } // Now go through the types that we've found, and set up the expressions for the criteria int numberOfMatchesEvaluated = 0; AbstractCriterion restrictionBuilder = null; foreach (var dataSerializationTypese in toReturn.ValueTypesToQuery.Distinct()) { AbstractCriterion restriction = null; global::System.Linq.Expressions.Expression <Func <object> > propertyExpression = null; global::System.Linq.Expressions.Expression <Func <object> > subkeyExpression = null; List <ValuePredicateType> validClauseTypes = null; var useLikeMatchForStrings = false; switch (dataSerializationTypese) { case DataSerializationTypes.SmallInt: case DataSerializationTypes.LargeInt: case DataSerializationTypes.Boolean: propertyExpression = () => integerVal.Value; subkeyExpression = () => integerVal.ValueKey; validClauseTypes = new List <ValuePredicateType>() { ValuePredicateType.Equal, ValuePredicateType.GreaterThan, ValuePredicateType.GreaterThanOrEqual, ValuePredicateType.LessThan, ValuePredicateType.LessThanOrEqual, ValuePredicateType.NotEqual }; break; case DataSerializationTypes.Decimal: propertyExpression = () => decimalVal.Value; subkeyExpression = () => decimalVal.ValueKey; validClauseTypes = new List <ValuePredicateType>() { ValuePredicateType.Equal, ValuePredicateType.GreaterThan, ValuePredicateType.GreaterThanOrEqual, ValuePredicateType.LessThan, ValuePredicateType.LessThanOrEqual, ValuePredicateType.NotEqual }; break; case DataSerializationTypes.String: propertyExpression = () => stringVal.Value; subkeyExpression = () => stringVal.ValueKey; validClauseTypes = new List <ValuePredicateType>() { ValuePredicateType.Equal, ValuePredicateType.NotEqual, ValuePredicateType.Contains, ValuePredicateType.StartsWith, ValuePredicateType.EndsWith, ValuePredicateType.MatchesWildcard }; break; case DataSerializationTypes.LongString: propertyExpression = () => longStrVal.Value; subkeyExpression = () => longStrVal.ValueKey; useLikeMatchForStrings = true; validClauseTypes = new List <ValuePredicateType>() { ValuePredicateType.Equal, ValuePredicateType.NotEqual, ValuePredicateType.Contains, ValuePredicateType.StartsWith, ValuePredicateType.EndsWith, ValuePredicateType.MatchesWildcard }; break; case DataSerializationTypes.Date: propertyExpression = () => dateVal.Value; subkeyExpression = () => dateVal.ValueKey; validClauseTypes = new List <ValuePredicateType>() { ValuePredicateType.Equal, ValuePredicateType.GreaterThan, ValuePredicateType.GreaterThanOrEqual, ValuePredicateType.LessThan, ValuePredicateType.LessThanOrEqual, ValuePredicateType.NotEqual, ValuePredicateType.Empty }; break; } if (!validClauseTypes.Contains(node.ValueExpression.ClauseType)) { throw new InvalidOperationException("A field of type {0} cannot be queried with operator {1}".InvariantFormat(dataSerializationTypese.ToString(), node.ValueExpression.ClauseType.ToString())); } // Based on the clause type, generate an NH criterion switch (node.ValueExpression.ClauseType) { case ValuePredicateType.Equal: restriction = GetRestrictionEq(fieldValue, useLikeMatchForStrings, propertyExpression, subkeyExpression, valueKey); break; case ValuePredicateType.NotEqual: restriction = !GetRestrictionEq(fieldValue, useLikeMatchForStrings, propertyExpression); break; case ValuePredicateType.LessThan: restriction = GetRestrictionLt(fieldValue, propertyExpression); break; case ValuePredicateType.LessThanOrEqual: restriction = GetRestrictionLtEq(fieldValue, propertyExpression); break; case ValuePredicateType.GreaterThan: restriction = GetRestrictionGt(fieldValue, propertyExpression); break; case ValuePredicateType.GreaterThanOrEqual: restriction = GetRestrictionGtEq(fieldValue, propertyExpression); break; case ValuePredicateType.Contains: restriction = GetRestrictionContains(fieldValue, propertyExpression); break; case ValuePredicateType.StartsWith: restriction = GetRestrictionStarts(fieldValue, propertyExpression); break; case ValuePredicateType.EndsWith: restriction = GetRestrictionEnds(fieldValue, propertyExpression); break; } // We might be dealing with multiple restrictions even for one field (e.g. if it's been stored once in String table, and another time in LongString) if (restriction != null) { if (numberOfMatchesEvaluated == 0) { restrictionBuilder = restriction; numberOfMatchesEvaluated++; } else { // If we're doing a second or later evaluation, turn the restriction into an Or to combine them all restrictionBuilder = Restrictions.Or(restriction, restrictionBuilder); } } } // Add the field name restriction var fieldNameRestriction = Restrictions.Eq(Projections.Property(() => def.Alias), fieldName); if (restrictionBuilder != null) { restrictionBuilder = Restrictions.And(restrictionBuilder, fieldNameRestriction); } else { restrictionBuilder = fieldNameRestriction; } // Build the query which will use the restrictions we've just generated var query = QueryOver.Of(() => agg); // Set up the basic joins (not that we're adding these to a Joins collection on our own type, not just doing // them on an NH query, so that we can optimise or merge the joins once the entire expression tree is evaluated // for example inside VisitBinary) toReturn.Joins.Add(new Join(() => agg.NodeVersion, () => version, JoinType.InnerJoin)); toReturn.Joins.Add(new Join(() => version.Attributes, () => att, JoinType.InnerJoin)); toReturn.Joins.Add(new Join(() => att.AttributeDefinition, () => def, JoinType.InnerJoin)); // Set up the joins for the value tables - only add joins for the tables that we know we want to actually query based on // what VisitField might have encountered and added to toReturn.ValueTypesToQuery foreach (var dataSerializationTypese in toReturn.ValueTypesToQuery.Distinct()) { Expression <Func <object> > path = null; Expression <Func <object> > alias = null; switch (dataSerializationTypese) { case DataSerializationTypes.SmallInt: case DataSerializationTypes.LargeInt: case DataSerializationTypes.Boolean: path = () => att.AttributeIntegerValues; alias = () => integerVal; break; case DataSerializationTypes.Decimal: path = () => att.AttributeDecimalValues; alias = () => decimalVal; break; case DataSerializationTypes.String: path = () => att.AttributeStringValues; alias = () => stringVal; break; case DataSerializationTypes.LongString: path = () => att.AttributeLongStringValues; alias = () => longStrVal; break; case DataSerializationTypes.Date: path = () => att.AttributeDateValues; alias = () => dateVal; break; } toReturn.Joins.Add(new Join(path, alias)); } toReturn.Subquery = query .Where(restrictionBuilder) .Select(x => x.NodeVersion.Id); toReturn.NhCriterion = restrictionBuilder; return(toReturn); }
public override QueryOver <NodeVersion> VisitFieldPredicate(FieldPredicateExpression node) { var fieldName = node.SelectorExpression.FieldName; var valueKey = node.SelectorExpression.ValueKey; var fieldValue = node.ValueExpression.Value; switch (fieldName.ToLowerInvariant()) { case "id": Guid idValue = GetIdValue(node); switch (node.ValueExpression.ClauseType) { case ValuePredicateType.Equal: return(QueryOver.Of <NodeVersion>().Where(x => x.Node.Id == idValue).Select(x => x.Id)); case ValuePredicateType.NotEqual: return(QueryOver.Of <NodeVersion>().Where(x => x.Node.Id != idValue).Select(x => x.Id));; default: throw new InvalidOperationException( "Cannot query an item by id by any other operator than == or !="); } } NodeVersion aliasNodeVersion = null; Attribute aliasAttribute = null; AttributeDefinition aliasAttributeDefinition = null; AttributeStringValue aliasStringValue = null; AttributeLongStringValue aliasLongStringValue = null; NodeRelation aliasNodeRelation = null; AttributeDateValue aliasDateValue = null; //TODO: This is going to need to lookup more than string values var queryString = QueryOver.Of <NodeVersion>(() => aliasNodeVersion) .JoinQueryOver <Attribute>(() => aliasNodeVersion.Attributes, () => aliasAttribute) .JoinQueryOver <AttributeDefinition>(() => aliasAttribute.AttributeDefinition, () => aliasAttributeDefinition) .Left.JoinQueryOver <AttributeStringValue>(() => aliasAttribute.AttributeStringValues, () => aliasStringValue) .Left.JoinQueryOver <AttributeLongStringValue>(() => aliasAttribute.AttributeLongStringValues, () => aliasLongStringValue) .Left.JoinQueryOver(() => aliasAttribute.AttributeDateValues, () => aliasDateValue) //select the field name... .Where(x => aliasAttributeDefinition.Alias == fieldName); if (!valueKey.IsNullOrWhiteSpace()) { //if the value key is specified, then add that to the query queryString = queryString.And(() => aliasStringValue.ValueKey == valueKey || aliasLongStringValue.ValueKey == valueKey).Select(x => x.Id); } //now, select the field value.... switch (node.ValueExpression.ClauseType) { case ValuePredicateType.Equal: var sqlCeCompatibleQuery = Restrictions.Or( Restrictions.Eq( Projections.Property <AttributeStringValue>(x => aliasStringValue.Value), fieldValue), Restrictions.Like( Projections.Property <AttributeLongStringValue>(x => aliasLongStringValue.Value), fieldValue as string, MatchMode.Exact)); return(queryString.And(sqlCeCompatibleQuery).Select(x => x.Id)); case ValuePredicateType.NotEqual: return(queryString.And(x => aliasStringValue.Value != fieldValue).Select(x => x.Id)); case ValuePredicateType.MatchesWildcard: case ValuePredicateType.Contains: return(queryString.And(Restrictions.Like(Projections.Property <AttributeStringValue>(x => aliasStringValue.Value), fieldValue as string, MatchMode.Anywhere)).Select(x => x.Id)); case ValuePredicateType.StartsWith: return(queryString.And(Restrictions.Like(Projections.Property <AttributeStringValue>(x => aliasStringValue.Value), fieldValue as string, MatchMode.Start)).Select(x => x.Id)); case ValuePredicateType.EndsWith: return(queryString.And(Restrictions.Like(Projections.Property <AttributeStringValue>(x => aliasStringValue.Value), fieldValue as string, MatchMode.End)).Select(x => x.Id)); case ValuePredicateType.LessThanOrEqual: return (queryString.And( Restrictions.Le(Projections.Property <AttributeDateValue>(x => aliasDateValue.Value), (DateTimeOffset)fieldValue))); case ValuePredicateType.GreaterThanOrEqual: return (queryString.And( Restrictions.Ge(Projections.Property <AttributeDateValue>(x => aliasDateValue.Value), (DateTimeOffset)fieldValue))); default: throw new InvalidOperationException( "This linq provider doesn't support a ClauseType of {0} for field {1}".InvariantFormat( node.ValueExpression.ClauseType.ToString(), fieldName)); } }