I'm trying to ellaborate a SEARCH CFQL method.
I have either a property TownId set or a property TownLabel in the entity Address:
In my SEARCH method I want to look for users having as a town, either the townLabel OR possible towns from the referential whoes name contains the value townLabel.
Long story short, my CFQL methods is as follow
SEARCH(string[] townIds, string townLabel) WHERE Adresses.TownId IN (@townIds) OR Adresses.TownLabel LIKE '%'+@townLabel+'%'
Despite the OR operator, the generated SQL appears with the AND operator as below.
My question: is it normal ?
CREATE PROCEDURE [dbo].[User_AdvancedSearch]
(
@townIds [nvarchar] (max) = NULL,
@townLabel [nvarchar] (256) = NULL,
@_orderBy0 [nvarchar] (64) = NULL,
@_orderByDirection0 [bit] = 0
)
AS
SET NOCOUNT ON
DECLARE @sql nvarchar(max), @paramlist nvarchar(max)
SELECT @sql=
'SELECT DISTINCT [User].[User_UserId], [User].[User_Name], [User].[User_Association_AssociationId], [User].[_trackLastWriteTime], [User].[_trackCreationTime], [User].[_trackLastWriteUser], [User].[_trackCreationUser], [User].[_rowVersion]
FROM [User]
LEFT OUTER JOIN [Address] ON ([User].[User_UserId] = [Address].[Address_User_UserId])
WHERE ((1 = 1) AND (1 = 1))'
SELECT @paramlist = '@townIds nvarchar (max),
@townLabel nvarchar (256),
@_orderBy0 nvarchar (64),
@_orderByDirection0 bit'
IF @townIds IS NOT NULL
SELECT @sql = @sql + ' AND ([Address].[Address_TownId] IN ((SELECT [Item] FROM [dbo].cf_SplitString(@townIds, nchar(1)))))'
IF @townLabel IS NOT NULL
SELECT @sql = @sql + ' AND (([Address].[Address_TownLabel] LIKE ((''%'' + @townLabel) + ''%'')))'
EXEC sp_executesql @sql, @paramlist,
@townIds,
@townLabel,
@_orderBy0,
@_orderByDirection0
RETURN
GO
The schema is given below
<cf:project defaultNamespace="WcfServices.Model" xmlns:cf="http://www.softfluent.com/codefluent/2005/1" xmlns:cfx="http://www.softfluent.com/codefluent/modeler/2008/1" xmlns:cfps="http://www.softfluent.com/codefluent/producers.sqlserver/2005/1" xmlns:cfom="http://www.softfluent.com/codefluent/producers.model/2005/1" xmlns:cfsps="http://www.softfluent.com/codefluent/producers.sqlpivotscript/2013/1" createDefaultMethodForms="true" createDefaultApplication="false" createDefaultHints="false">
<cf:import path="Default.Surface.cfp" />
<cf:entity name="Association" namespace="Example.Model.Association" categoryPath="/WcfServices.Model">
<cf:property name="AssociationId" key="true" persistenceEnforce="true" />
<cf:property name="Label" persistenceEnforce="true" />
<cf:property name="Users" typeName="Example.Model.Association.UserCollection" relationPropertyName="Association" />
</cf:entity>
<cf:producer name="SQL Server" typeName="CodeFluent.Producers.SqlServer.SqlServerProducer, CodeFluent.Producers.SqlServer">
<cf:configuration produceViews="true" targetDirectory="..\WcfServices.persistence" cfx:targetProject="..\WcfServices.persistence\WcfServices.persistence.sqlproj" cfx:targetProjectLayout="Update, DontRemove" />
</cf:producer>
<cf:producer name="Business Object Model (BOM)" typeName="CodeFluent.Producers.CodeDom.CodeDomProducer, CodeFluent.Producers.CodeDom">
<cf:configuration compileWithVisualStudio="true" compile="false" codeDomProviderTypeName="CSharp" targetDirectory="..\WcfServices.model" cfx:targetProject="..\WcfServices.model\WcfServices.model.csproj" cfx:targetProjectLayout="Update">
</cf:configuration>
</cf:producer>
<cf:entity name="User" namespace="Example.Model.Association" categoryPath="/WcfServices.Model">
<cf:property name="UserId" key="true" persistenceEnforce="true" />
<cf:property name="Name" persistenceEnforce="true" />
<cf:property name="Association" typeName="Example.Model.Association.Association" relationPropertyName="Users" />
<cf:property name="Adresses" typeName="Example.Model.Association.AddressCollection" relationPropertyName="User" persistenceEnforce="true" />
<cf:method name="AdvancedSearch" body="SEARCH(string[] townIds, string townLabel) WHERE Adresses.TownId IN (@townIds) OR Adresses.TownLabel LIKE '%%'+@townLabel+'%%'" />
</cf:entity>
<cf:producer name="SQL Server Pivot Script" typeName="CodeFluent.Producers.SqlServer.SqlPivotScriptProducer, CodeFluent.Producers.SqlServer">
<cf:configuration targetDirectory="..\WcfServices.web" cfx:targetProject="..\WcfServices.web\WcfServices.web.csproj" cfx:targetProjectLayout="Update" />
</cf:producer>
<cf:entity name="Address" namespace="Example.Model.Association" categoryPath="/WcfServices.Model">
<cf:property name="AddressId" key="true" persistenceEnforce="true" />
<cf:property name="Line" persistenceEnforce="true" />
<cf:property name="User" typeName="Example.Model.Association.User" relationPropertyName="Adresses" persistenceEnforce="true" />
<cf:property name="TownLabel" />
<cf:property name="TownId" typeName="guid" />
</cf:entity>
</cf:project>
EDIT 15/09/2016 - adding original CFQL + schema.
Original CFQL method:
SEARCH (string firstname, string name, int[] groups, string postalCode, string townLabel, string mail, string[] townId, guid structureId, guid countryId) WHERE Firstname LIKE '%'+@firstname+'%' AND Name LIKE '%'+@name+'%' AND (Address.PostalCode LIKE '%'+@postalCode+'%' OR StructureContacts.Address.PostalCode LIKE '%'+@postalCode+'%') AND ( Address.TownLabel LIKE '%'+@townLabel+'%' OR StructureContacts.Address.TownLabel LIKE '%'+@townLabel+'%' OR Address.TownId IN (@townId) OR StructureContacts.Address.TownId IN(@townId)) AND (StructureContacts.Groups.Value IN (@groups) OR Groups.Value IN (@groups)) AND StructureContacts.Structure.StructureId = @structureId and (Address.Email LIKE '%'+@mail+'%' OR StructureContacts.Address.Email LIKE '%'+@mail+'%') AND (Address.CountryId = @countryId OR StructureContacts.Address.CountryId = @countryId) order by Name, Firstname
Schema:
<cf:project defaultNamespace="Example.Models" xmlns:cf="http://www.softfluent.com/codefluent/2005/1">
<cf:enumeration name="enumStructureType" namespace="Example.Models.Contact.Structure" categoryPath="/RH">
<cf:enumerationValue name="ENTERPRISE" />
<cf:enumerationValue name="ASSOCIATION" />
<cf:enumerationValue name="OTHER_ASSOCIATION" />
<cf:enumerationValue name="SUPPLIER" />
<cf:enumerationValue name="PUBLIC_ORGANIZATION" />
</cf:enumeration>
<cf:entity name="Structure" defaultUsePersistenceDefaultValue="false" defaultPersistenceEnforce="false" namespace="Example.Models.Contact.Structure" categoryPath="/RH" storeName="ExampleStoreName">
<cf:property name="StructureId" key="true" />
<cf:property name="Sigle" />
<cf:property name="CorporateName" />
<cf:property name="Code" />
<cf:property name="Comment">
<cf:rule typeName="StringValidate" maxLength="2000" />
</cf:property>
<cf:property name="Siret" xmlns:cf="http://www.softfluent.com/codefluent/2005/1" collectionKey="false">
<cf:rule typeName="RegularExpressionValidate" expression="[\d]{14,14}" />
</cf:property>
<cf:property name="Type" xmlns:cf="http://www.softfluent.com/codefluent/2005/1" defaultValue="EstablishmentType.PRINCIPAL" typeName="{0}.Contact.Structure.enumStructureType" collectionKey="false" />
<cf:property name="Groups" set="true" cascadeSave="After" cascadeDelete="Before" typeName="{0}.Contact.Contact.GroupCollection" />
<cf:property name="ApeId" typeName="guid" />
<cf:property name="Address" cascadeSave="After" cascadeDelete="Before" typeName="{0}.Contact.Contact.Address" relationSchema="Contact" />
<cf:property name="EstablishmentType" typeName="{0}.Contact.Structure.enumEstablishmentType" />
<cf:property name="ParentStructure" readOnSave="true" typeName="{0}.Contact.Structure.Structure" relationPropertyName="ChildrenStructures" />
<cf:property name="ChildrenStructures" set="true" cascadeSave="After" cascadeDelete="Before" typeName="{0}.Contact.Structure.StructureCollection" relationPropertyName="ParentStructure" />
<cf:property name="OpeningHours" maxLength="2000" />
<cf:method name="SimpleSearchStructures" body="SEARCH (string keyword) WHERE CorporateName LIKE '%%'+@keyword+'%%' OR Code LIKE '%%'+@keyword+'%%' OR Comment LIKE '%%'+@keyword+'%%' OR Sigle LIKE '%%'+@keyword+'%%' OR Siret LIKE '%%'+@keyword+'%%' OR Address.Email LIKE '%%'+@keyword+'%%' ORDER BY CorporateName" />
<cf:method name="AdvancedSearchStructures" body="SEARCH (string corporateName, string email, string postalCode, string townLabel, string[] townIds, int[] groups, guid countryId, int[] types) WHERE CorporateName LIKE '%%'+@corporateName+'%%' AND Address.Email LIKE '%%'+@email+'%%' AND (Address.TownLabel LIKE '%%'+@townLabel+'%%' OR Address.TownId IN (@townIds)) AND Address.PostalCode LIKE '%%'+@postalCode+'%%' AND Address.CountryId = @countryId AND Groups.Value IN (@groups) AND Type IN (@types) ORDER BY CorporateName" />
<cf:rule typeName="OnBeforeSave" methodName="BeforeSave" />
<cf:method name="DeleteById" body="DELETE(guid id) WHERE StructureId = @id" />
</cf:entity>
<cf:entity name="StructureAssociation" baseTypeName="Example.Models.Contact.Structure.Structure" namespace="Example.Models.Contact.Structure" categoryPath="/Example.Models" storeName="ExampleStoreName">
<cf:property name="ParutionDateOJ" xmlns:cf="http://www.softfluent.com/codefluent/2005/1" typeName="date" persistenceEnforce="true" collectionKey="false" />
<cf:property name="BasinId" xmlns:cf="http://www.softfluent.com/codefluent/2005/1" typeName="guid" relationSchema="Contact" persistenceEnforce="true" collectionKey="false" />
<cf:property name="ReceiptNum" xmlns:cf="http://www.softfluent.com/codefluent/2005/1" persistenceEnforce="true" collectionKey="false" />
<cf:property name="PrefectureId" typeName="guid" persistenceEnforce="true" />
<cf:property name="CreationDate" typeName="date" persistenceEnforce="true" />
<cf:property name="CartePecheAappmaId" persistenceEnforce="true" />
<cf:method name="LoadAssociationStructure" body="LOADONE WHERE EstablishmentType = 3" />
</cf:entity>
<cf:entity name="StructureContact" defaultUsePersistenceDefaultValue="false" setType="List" namespace="Example.Models.Contact.Structure" categoryPath="/RH" storeName="ExampleStoreName">
<cf:property name="Function" defaultValue="enumFunctionType.PRESIDENT" typeName="{0}.Contact.Structure.enumFunctionType" persistenceEnforce="true" collectionKey="false" />
<cf:property name="StartDateFunction" usePersistenceDefaultValue="true" typeName="date" persistenceEnforce="true" collectionKey="false" />
<cf:property name="EndDateFunction" usePersistenceDefaultValue="true" typeName="date" persistenceEnforce="true" collectionKey="false" />
<cf:property name="Contact" typeName="{0}.Contact.Contact.Contact" relationPropertyName="StructureContacts" relationSchema="Contact" persistenceEnforce="true" />
<cf:property name="Address" cascadeSave="After" cascadeDelete="Before" typeName="{0}.Contact.Contact.Address" relationSchema="Contact" persistenceEnforce="true" />
<cf:property name="Groups" set="true" cascadeSave="After" cascadeDelete="Before" typeName="{0}.Contact.Contact.GroupCollection" persistenceEnforce="true" />
<cf:property name="DocumentUrl" typeName="guid" persistenceEnforce="true" />
<cf:property name="Structure" typeName="{0}.Contact.Structure.Structure" persistenceEnforce="true">
<cf:attribute name="Newtonsoft.Json.JsonIgnore" class="" />
</cf:property>
<cf:property name="StructureContactId" key="true" persistenceEnforce="true" />
<cf:property name="AdditionalDate" usePersistenceDefaultValue="true" typeName="date" persistenceEnforce="true" />
<cf:property name="DocumentName" persistenceEnforce="true" />
<cf:method name="LoadBoardMembers" body="LOAD (int[] functions) WHERE Function IN (@functions)" />
</cf:entity>
<cf:entity name="StructureEnterprise" baseTypeName="Example.Models.Contact.Structure.Structure" namespace="Example.Models.Contact.Structure" categoryPath="/Example.Models" storeName="ExampleStoreName">
<cf:property name="VATNum" xmlns:cf="http://www.softfluent.com/codefluent/2005/1" persistenceEnforce="true" collectionKey="false" />
</cf:entity>
<cf:entity name="StructureOtherAssociation" baseTypeName="Example.Models.Contact.Structure.Structure" namespace="Example.Models.Contact.Structure" categoryPath="/Example.Models" storeName="ExampleStoreName">
<cf:property name="ReceiptNum" xmlns:cf="http://www.softfluent.com/codefluent/2005/1" persistenceEnforce="true" collectionKey="false" />
<cf:property name="SkillTerritoryType" typeName="{0}.Contact.Structure.enumStructureSkillTerritoryType" persistenceEnforce="true" />
</cf:entity>
<cf:entity name="Address" defaultUsePersistenceDefaultValue="false" namespace="Example.Models.Contact.Contact" categoryPath="/RH" persistenceName="Address" storeName="ExampleStoreName">
<cf:property name="AddressId" key="true" persistenceEnforce="true" />
<cf:property name="Line1" persistenceEnforce="true" />
<cf:property name="Line2" persistenceEnforce="true" />
<cf:property name="IsActive" typeName="bool" persistenceEnforce="true" />
<cf:property name="Landline" persistenceEnforce="true" />
<cf:property name="Email" persistenceEnforce="true">
<cf:rule typeName="EmailValidate" />
</cf:property>
<cf:property name="Fax" persistenceEnforce="true" />
<cf:property name="Website" persistenceEnforce="true" />
<cf:property name="Mobile" persistenceEnforce="true" />
<cf:property name="DirectLine" persistenceEnforce="true" />
<cf:property name="ProfessionalLine" persistenceEnforce="true" />
<cf:property name="TownId" typeName="guid" persistenceEnforce="true" />
<cf:property name="TownLabel" persistenceEnforce="true" />
<cf:property name="CountryId" typeName="guid" persistenceEnforce="true" />
<cf:property name="PostalCode" persistenceEnforce="true" />
<cf:rule typeName="OnBeforeSave" methodName="BeforeSave" />
</cf:entity>
<cf:entity name="Contact" defaultUsePersistenceDefaultValue="false" namespace="Example.Models.Contact.Contact" categoryPath="/RH" persistenceName="Contact" storeName="ExampleStoreName">
<cf:property name="Name" persistenceEnforce="true" />
<cf:property name="Firstname" persistenceEnforce="true" />
<cf:property name="Civility" defaultValue="CivilityContact.Mr" typeName="{0}.Global.Civility" persistenceEnforce="true" />
<cf:property name="DateOfBirth" serializationNullable="true" modelNullable="true" typeName="date" persistenceEnforce="true" />
<cf:property name="Comment" persistenceEnforce="true">
<cf:rule typeName="StringValidate" maxLength="2000" />
</cf:property>
<cf:property name="ContactId" key="true" persistenceEnforce="true" />
<cf:property name="StructureContacts" set="true" cascadeSave="After" cascadeDelete="Before" typeName="{0}.Contact.Structure.StructureContactCollection" relationPropertyName="Contact" relationSchema="Contact" persistenceEnforce="true" />
<cf:property name="Address" cascadeSave="After" cascadeDelete="Before" typeName="{0}.Contact.Contact.Address" relationSchema="Contact" persistenceEnforce="true" />
<cf:property name="TownOfBirthLabel" persistenceEnforce="true" />
<cf:property name="TownIdOfBirth" typeName="guid" persistenceEnforce="true" />
<cf:property name="CountryIdOfBirth" typeName="guid" persistenceEnforce="true" />
<cf:property name="DepartmentIdOfBirth" typeName="guid" persistenceEnforce="true" />
<cf:property name="PostalCode" persistenceEnforce="true" />
<cf:property name="Groups" set="true" cascadeSave="After" cascadeDelete="Before" typeName="{0}.Contact.Contact.GroupCollection" persistenceEnforce="true" />
<cf:property name="CartePecheMemberId" persistenceEnforce="true" />
<cf:method name="AdvancedSearchContactsTownLabel" body="SEARCH (string firstname, string name, int[] groups, string postalCode, string townLabel, string mail, string[] townId, guid structureId, guid countryId) WHERE Firstname LIKE '%%'+@firstname+'%%' AND Name LIKE '%%'+@name+'%%' AND (Address.PostalCode LIKE '%%'+@postalCode+'%%' OR StructureContacts.Address.PostalCode LIKE '%%'+@postalCode+'%%') AND ( Address.TownLabel LIKE '%%'+@townLabel+'%%' OR StructureContacts.Address.TownLabel LIKE '%%'+@townLabel+'%%' OR Address.TownId IN (@townId) OR StructureContacts.Address.TownId IN(@townId)) AND (StructureContacts.Groups.Value IN (@groups) OR Groups.Value IN (@groups)) AND StructureContacts.Structure.StructureId = @structureId and (Address.Email LIKE '%%'+@mail+'%%' OR StructureContacts.Address.Email LIKE '%%'+@mail+'%%') AND (Address.CountryId = @countryId OR StructureContacts.Address.CountryId = @countryId) order by Name, Firstname" />
<cf:method name="SimpleSearchContacts" body="SEARCH(string keywords) WHERE Firstname LIKE '%%'+@keywords+'%%' OR Name LIKE '%%'+@keywords+'%%' OR Address.Email LIKE '%%'+@keywords+'%%' OR StructureContacts.Address.Email LIKE '%%'+@keywords+'%%' order by Name, Firstname" />
<cf:rule typeName="OnBeforeSave" methodName="BeforeSave" />
<cf:method name="SearchContactByName" body="SEARCH(string nameOrFirstName, int[] functions) WHERE (Name LIKE '%%'+@nameOrFirstName+'%%' OR Firstname LIKE '%%'+@nameOrFirstName+'%%') AND StructureContacts.Function IN (@functions)" />
<cf:method name="LoadContactsByDateFunction" body="LOAD (date currentDate, int[] functions) WHERE StructureContacts.Function IN (@functions) AND ( StructureContacts.StartDateFunction <= @currentDate OR NOT StructureContacts.StartDateFunction EXISTS )
 AND ( StructureContacts.EndDateFunction > @currentDate OR NOT StructureContacts.EndDateFunction EXISTS )" />
<cf:method name="DeleteById" body="DELETE(guid id) WHERE ContactId = @id" />
<cf:method name="AdvancedSearchContactTownId" body="SEARCH (string firstname, string name, int[] groups, string postalCode, string townLabel, string mail, string[] townId, guid structureId, guid countryId) WHERE Firstname LIKE '%%'+@firstname+'%%' AND Name LIKE '%%'+@name+'%%' AND (Address.PostalCode LIKE '%%'+@postalCode+'%%' OR StructureContacts.Address.PostalCode LIKE '%%'+@postalCode+'%%') AND (Address.TownId IN (@townId) OR StructureContacts.Address.TownId IN(@townId) ) AND (StructureContacts.Groups.Value IN (@groups) OR Groups.Value IN (@groups)) AND StructureContacts.Structure.StructureId = @structureId and (Address.Email LIKE '%%'+@mail+'%%' OR StructureContacts.Address.Email LIKE '%%'+@mail+'%%') AND (Address.CountryId = @countryId OR StructureContacts.Address.CountryId = @countryId) order by Name, Firstname" />
</cf:entity>
<cf:entity name="Group" defaultUsePersistenceDefaultValue="false" namespace="Example.Models.Contact.Contact" categoryPath="/RH" storeName="ExampleStoreName">
<cf:property name="GroupId" key="true" persistenceEnforce="true" />
<cf:property name="Value" defaultValue="enumGroupType.DGS" typeName="int" persistenceEnforce="true" />
</cf:entity>
<cf:entity name="StructureSupplier" baseTypeName="Example.Models.Contact.Structure.Structure" namespace="Example.Models.Contact.Structure" categoryPath="/Example.Models" storeName="ExampleStoreName">
<cf:property name="CartePecheDepositaireId" persistenceEnforce="true" />
<cf:property name="NumberExt" persistenceEnforce="true" />
<cf:property name="DocumentUrl" persistenceEnforce="true" />
<cf:property name="DocumentName" persistenceEnforce="true" />
<cf:property name="IsKeyAccount" typeName="bool" persistenceEnforce="true" />
<cf:property name="ConventionDate" typeName="date" persistenceEnforce="true" />
</cf:entity>
<cf:enumeration name="enumEstablishmentType" namespace="Example.Models.Contact.Structure" categoryPath="/Example.Models">
<cf:enumerationValue name="HEAD_OFFICE" />
<cf:enumerationValue name="SECONDARY" />
<cf:enumerationValue name="DELEGATION" />
<cf:enumerationValue name="ASSOCIATION" />
</cf:enumeration>
<cf:enumeration name="enumFunctionType" namespace="Example.Models.Contact.Structure" categoryPath="/Example.Models">
<cf:enumerationValue name="DIRECTOR" />
<cf:enumerationValue name="EMPLOYEE" />
<cf:enumerationValue name="ELECTED" />
<cf:enumerationValue name="VOLUNTEER" />
<cf:enumerationValue name="INDIVIDUAL" />
<cf:enumerationValue name="PRESIDENT" />
<cf:enumerationValue name="VICE_PRESIDENT" />
<cf:enumerationValue name="TREASURER" />
<cf:enumerationValue name="SECRETARY" />
<cf:enumerationValue name="BOARD_MEMBER" />
<cf:enumerationValue name="LEGAL_MEMBER" />
<cf:enumerationValue name="BY_LAW_MEMBER" />
<cf:enumerationValue name="ACCOUNT_INSPECTOR" />
<cf:enumerationValue name="RESELLER" />
<cf:enumerationValue name="OWNER" />
<cf:enumerationValue name="CONTRACTOR" />
<cf:enumerationValue name="GENERAL_CONTRACTOR" />
<cf:enumerationValue name="CONTRACTING_AUTHORITY" />
<cf:enumerationValue name="LESSOR" />
<cf:enumerationValue name="OTHER" />
<cf:enumerationValue name="MEMBER" />
</cf:enumeration>
<cf:enumeration name="enumStructureSkillTerritoryType" namespace="Example.Models.Contact.Structure" categoryPath="/Example.Models">
<cf:enumerationValue name="LOCAL" />
<cf:enumerationValue name="DEPARTEMENTAL" />
<cf:enumerationValue name="REGIONAL" />
<cf:enumerationValue name="NATIONAL" />
</cf:enumeration>
<cf:entity name="StructurePublicOrganization" baseTypeName="Example.Models.Contact.Structure.Structure" namespace="Example.Models.Contact.Structure" categoryPath="/Example.Models" storeName="ExampleStoreName">
<cf:property name="ReceiptNum" persistenceEnforce="true" />
</cf:entity>
</cf:project>
The generated SQL (note the extra AND in townLabel parameter)
CREATE PROCEDURE [Contact].[Contact_AdvancedSearchContactsTownLabel]
(
@firstname [nvarchar] (256) = NULL,
@name [nvarchar] (256) = NULL,
@groups [Contact].[cf_type_Contact_AdvancedSearchContactsTownLabel_2] READONLY,
@postalCode [nvarchar] (256) = NULL,
@townLabel [nvarchar] (256) = NULL,
@mail [nvarchar] (256) = NULL,
@townId [nvarchar] (max) = NULL,
@structureId [uniqueidentifier] = NULL,
@countryId [uniqueidentifier] = NULL,
@_orderBy0 [nvarchar] (64) = NULL,
@_orderByDirection0 [bit] = 0
)
AS
SET NOCOUNT ON
DECLARE @_c_groups int; SELECT @_c_groups= COUNT(*) FROM @groups
DECLARE @sql nvarchar(max), @paramlist nvarchar(max)
SELECT @sql=
'SELECT DISTINCT [Contact].[Contact].[Contact_Name], [Contact].[Contact].[Contact_Firstname], [Contact].[Contact].[Contact_Civility], [Contact].[Contact].[Contact_DateOfBirth], [Contact].[Contact].[Contact_Comment], [Contact].[Contact].[Contact_ContactId], [Contact].[Contact].[Contact_Address_AddressId], [Contact].[Contact].[Contact_TownOfBirthLabel], [Contact].[Contact].[Contact_TownIdOfBirth], [Contact].[Contact].[Contact_CountryIdOfBirth], [Contact].[Contact].[Contact_DepartmentIdOfBirth], [Contact].[Contact].[Contact_PostalCode], [Contact].[Contact].[Contact_CartePecheMemberId], [Contact].[Contact].[_trackLastWriteTime], [Contact].[Contact].[_trackCreationTime], [Contact].[Contact].[_trackLastWriteUser], [Contact].[Contact].[_trackCreationUser], [Contact].[Contact].[_rowVersion]
FROM [Contact].[Contact]
LEFT OUTER JOIN [Contact].[Address] ON ([Contact].[Contact].[Contact_Address_AddressId] = [Contact].[Address].[Address_AddressId])
LEFT OUTER JOIN [Contact].[StructureContact] ON ([Contact].[Contact].[Contact_ContactId] = [Contact].[StructureContact].[StructureContact_Contact_ContactId])
LEFT OUTER JOIN [Contact].[Address] [Address$1] ON ([Contact].[StructureContact].[StructureContact_Address_AddressId] = [Address$1].[Address_AddressId])
LEFT OUTER JOIN [Contact].[StructureContact_Groups_Group] ON ([Contact].[StructureContact].[StructureContact_StructureContactId] = [Contact].[StructureContact_Groups_Group].[StructureContact_StructureContactId])
LEFT OUTER JOIN [Contact].[Group] ON ([Contact].[StructureContact_Groups_Group].[Group_GroupId] = [Contact].[Group].[Group_GroupId])
LEFT OUTER JOIN [Contact].[Structure] ON ([Contact].[StructureContact].[StructureContact_Structure_StructureId] = [Contact].[Structure].[Structure_StructureId])
LEFT OUTER JOIN [Contact].[Address] [Address$2] ON ([Contact].[Contact].[Contact_Address_AddressId] = [Address$2].[Address_AddressId])
LEFT OUTER JOIN [Contact].[Contact_Groups_Group] ON ([Contact].[Contact].[Contact_ContactId] = [Contact].[Contact_Groups_Group].[Contact_ContactId])
LEFT OUTER JOIN [Contact].[Group] [Group$1] ON ([Contact].[Contact_Groups_Group].[Group_GroupId] = [Group$1].[Group_GroupId])
LEFT OUTER JOIN [Contact].[Address] [Address$3] ON ([Contact].[Contact].[Contact_Address_AddressId] = [Address$3].[Address_AddressId])
WHERE (((1 = 1) AND ((1 = 1) AND ((1 = 1) AND ((1 = 1) AND ((1 = 1) AND ((1 = 1) AND ((1 = 1) AND (1 = 1)))))))) AND (1 = 1))'
SELECT @paramlist = '@firstname nvarchar (256),
@name nvarchar (256),
@groups [Contact].[cf_type_Contact_AdvancedSearchContactsTownLabel_2] READONLY,
@postalCode nvarchar (256),
@townLabel nvarchar (256),
@mail nvarchar (256),
@townId nvarchar (max),
@structureId uniqueidentifier,
@countryId uniqueidentifier,
@_orderBy0 nvarchar (64),
@_orderByDirection0 bit'
IF @firstname IS NOT NULL
SELECT @sql = @sql + ' AND (([Contact].[Contact].[Contact_Firstname] LIKE ((''%'' + @firstname) + ''%'')))'
IF @name IS NOT NULL
SELECT @sql = @sql + ' AND (([Contact].[Contact].[Contact_Name] LIKE ((''%'' + @name) + ''%'')))'
IF @_c_groups > 0
SELECT @sql = @sql + ' AND (([Contact].[Group].[Group_Value] IN ((SELECT * FROM @groups)) OR [Group$1].[Group_Value] IN ((SELECT * FROM @groups))))'
IF @postalCode IS NOT NULL
SELECT @sql = @sql + ' AND ((([Contact].[Address].[Address_PostalCode] LIKE ((''%'' + @postalCode) + ''%'')) OR ([Address$1].[Address_PostalCode] LIKE ((''%'' + @postalCode) + ''%''))))'
IF @townLabel IS NOT NULL
SELECT @sql = @sql + ' AND ((([Address$2].[Address_TownLabel] LIKE ((''%'' + @townLabel) + ''%'')) OR (([Contact].[Address].[Address_TownLabel] LIKE ((''%'' + @townLabel) + ''%'')) OR ([Contact].[Address].[Address_TownId] IN ((SELECT [Item] FROM [dbo].cf_SplitString(@townId, nchar(1)))) OR [Contact].[Address].[Address_TownId] IN ((SELECT [Item] FROM [dbo].cf_SplitString(@townId, nchar(1))))))) AND ([Contact].[Address].[Address_TownLabel] LIKE ((''%'' + @townLabel) + ''%'')))'
IF @mail IS NOT NULL
SELECT @sql = @sql + ' AND ((([Address$3].[Address_Email] LIKE ((''%'' + @mail) + ''%'')) OR ([Contact].[Address].[Address_Email] LIKE ((''%'' + @mail) + ''%''))))'
IF @townId IS NOT NULL
SELECT @sql = @sql + ' AND (([Contact].[Address].[Address_TownId] IN ((SELECT [Item] FROM [dbo].cf_SplitString(@townId, nchar(1)))) OR [Contact].[Address].[Address_TownId] IN ((SELECT [Item] FROM [dbo].cf_SplitString(@townId, nchar(1))))))'
IF @structureId IS NOT NULL
SELECT @sql = @sql + ' AND (([Contact].[Structure].[Structure_StructureId] = @structureId))'
IF @countryId IS NOT NULL
SELECT @sql = @sql + ' AND ((([Contact].[Address].[Address_CountryId] = @countryId) OR ([Contact].[Address].[Address_CountryId] = @countryId)))'
SELECT @sql = @sql + ' ORDER BY [Contact].[Contact].[Contact_Name] ASC,[Contact].[Contact].[Contact_Firstname] ASC'
EXEC sp_executesql @sql, @paramlist,
@firstname,
@name,
@groups,
@postalCode,
@townLabel,
@mail,
@townId,
@structureId,
@countryId,
@_orderBy0,
@_orderByDirection0
RETURN
GO
EDIT 16/09/2016-possible workarounds found.
I found two possible workarounds:
First is to have a simpler search method with the rest of parameters (no townId, no townLabel), and to re-filter in memory with a LINQ mechanism.
Second is to go use generated code in a RAW method and adapt it to make it work the way we want.
Search
methods are very tricky to generate. In fact, the producer must split the body of the method by parameters. Then it creates IF @param IS NOT NULL
statement and combine them using an operator (by default AND
). If you want to change this operator, you can add the following xml attribute at the method:
<cf:method cfps:searchOperation="OR" ... />
If you don't have too many arguments (1 or 2) you can use a LOAD method with nullable parameters:
<cf:method name="LoadNullable" body="LOAD(string text1, string text2) WHERE Name = @text1 AND Name = @text2">
<cf:parameter nullable="True" name="text1" modelNullable="False" />
</cf:method>
The generated code looks like:
CREATE PROCEDURE [dbo].[Customer_LoadNullable]
(
@text1 [nvarchar] (256) = NULL,
@text2 [nvarchar] (256)
)
AS
SET NOCOUNT ON
IF(@text1 IS NULL)
BEGIN
SELECT [Customer].[Customer_Id], [Customer].[Customer_Name]
FROM [Customer]
WHERE ([Customer].[Customer_Name] = @text2)
END
ELSE
BEGIN
SELECT [Customer].[Customer_Id], [Customer].[Customer_Name]
FROM [Customer]
WHERE (([Customer].[Customer_Name] = @text1) AND ([Customer].[Customer_Name] = @text2))
END
This way you don't have any issue with the OR
and AND
, but this is not suitable for methods with many nullable parameters.