{"id":22881409,"url":"https://github.com/nicogis/doublemetaphonexaf","last_synced_at":"2025-03-31T15:51:08.204Z","repository":{"id":80808322,"uuid":"531966679","full_name":"nicogis/DoubleMetaphoneXAF","owner":"nicogis","description":"DoubleMetaphone XAF","archived":false,"fork":false,"pushed_at":"2022-09-03T09:00:06.000Z","size":119,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-06T21:31:33.296Z","etag":null,"topics":["devexpress","doublemetaphone","metaphone","metaphone-match","webforms","xaf"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nicogis.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-09-02T14:49:41.000Z","updated_at":"2023-06-30T23:16:50.000Z","dependencies_parsed_at":null,"dependency_job_id":"618b5500-d74e-4f1f-9e7d-52ce16047ce9","html_url":"https://github.com/nicogis/DoubleMetaphoneXAF","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicogis%2FDoubleMetaphoneXAF","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicogis%2FDoubleMetaphoneXAF/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicogis%2FDoubleMetaphoneXAF/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicogis%2FDoubleMetaphoneXAF/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nicogis","download_url":"https://codeload.github.com/nicogis/DoubleMetaphoneXAF/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246491619,"owners_count":20786225,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["devexpress","doublemetaphone","metaphone","metaphone-match","webforms","xaf"],"created_at":"2024-12-13T17:33:38.875Z","updated_at":"2025-03-31T15:51:08.172Z","avatar_url":"https://github.com/nicogis.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Double Metaphone XAF\n\nThis is a PoC to use [DoubleMetaphone](https://en.wikipedia.org/wiki/Metaphone) algorithm in XAF\n\n- Build DoubleMetaphone project\n\n- Register [dll in SQL Server](https://docs.microsoft.com/en-us/sql/relational-databases/clr-integration/database-objects/getting-started-with-clr-integration?view=sql-server-ver16)\n\n  You can follow these steps (here I am using Northwind):\n    \n\n```\u003clanguage\u003e\n        ALTER DATABASE Northwind\n        SET TRUSTWORTHY ON;\n\n        CREATE ASSEMBLY DoubleMetaphone\n        FROM 'C:\\Temp\\DoubleMetaphone.dll' WITH PERMISSION_SET = SAFE\n\n        ALTER DATABASE Northwind\n        SET TRUSTWORTHY OFF;\n```\n\nVisualize list of assembly in db\n```\u003clanguage\u003e\n    SELECT * from sys.assemblies\n```\n\nFrom Assembly select DoubleMetaphone and create script from assembly in clipboard\n![create script from assembly](https://github.com/nicogis/DoubleMetaphoneXAF/blob/master/DoubleMetaphone/images/CreateAssembly.png)\nClipboard:\n\n```\u003clanguage\u003e\nCREATE ASSEMBLY [DoubleMetaphone]\nFROM 0x4D5A90...\nWITH PERMISSION_SET = SAFE\nGO\n```\n\nCopy 0x4D5A90... in variable @asmBin and run this script to add assembly in trusted assembly\n\n```\u003clanguage\u003e\nUSE master;\nGO\nDECLARE @clrName nvarchar(4000) = 'doublemetaphone, version=0.0.0.0, culture=neutral, publickeytoken=null, processorarchitecture=msil'\nDECLARE @asmBin varbinary(max) = 0x4D5A90...;\nDECLARE @hash varbinary(64);\n\nSELECT @hash = HASHBYTES('SHA2_512', @asmBin);\n\nEXEC sys.sp_add_trusted_assembly @hash = @hash,\n                                 @description = @clrName;\n```\n\nVisualize list of assembly trusted\n```\u003clanguage\u003e\nselect * FROM sys.trusted_assemblies\n```\n\nCreate function in db\n\n```\u003clanguage\u003e\nCREATE FUNCTION dbo.udf_double_metaphone(@value nvarchar(max)) \nRETURNS nvarchar(max)   \nAS EXTERNAL NAME DoubleMetaphone.DoubleMetaphoneUDT.DoubleMetaphoneExec;   \nGO \n```\n\nEnable crl\n```\u003clanguage\u003e\n\nEXEC sp_configure 'clr enabled', 1;  \nRECONFIGURE;  \nGO \n```\n\n\nIn project XAF agnostic module create a custom function\n\n```\u003clanguage\u003e\n    public class DoubleMetaphone : ICustomFunctionOperatorFormattable\n    {\n        public string Name\n        {\n            get\n            {\n                return \"DoubleMetaphone\";\n            }\n        }\n        public object Evaluate(params object[] operands)\n        {\n            throw new NotImplementedException();\n        }\n        public Type ResultType(params Type[] operands)\n        {\n            return typeof(object);\n        }\n        static DoubleMetaphone()\n        {\n            DoubleMetaphone instance = new DoubleMetaphone();\n            if (CriteriaOperator.GetCustomFunction(instance.Name) == null)\n            {\n                CriteriaOperator.RegisterCustomFunction(instance);\n            }\n        }\n        public static void Register()\n        {\n        }\n\n        public string Format(Type providerType, params string[] operands)\n        {\n            if (providerType == typeof(MSSqlConnectionProvider))\n            {\n               \n                return $\"dbo.udf_double_metaphone({operands[0]}) = {operands[1]}\";\n            }\n                \n            throw new NotSupportedException($\"This provider is not supported: {providerType.Name}\");           \n        }\n    }\n```\n\nIn module.cs register the custom function\n\n```\u003clanguage\u003e\npublic sealed partial class DoubleMetaphoneXAFModule : ModuleBase {\n        public DoubleMetaphoneXAFModule() {\n            InitializeComponent();\n            Functions.DoubleMetaphone.Register();\n            ....\n        }\n        \n    }\n```\n\nAdd a controller to custom search standard \n```\u003clanguage\u003e\npublic partial class VCSearchDoubleMetaphone : ViewController\n    {\n        // Use CodeRush to create Controllers and Actions with a few keystrokes.\n        // https://docs.devexpress.com/CodeRushForRoslyn/403133/\n        public VCSearchDoubleMetaphone()\n        {\n            InitializeComponent();\n            // Target required Views (via the TargetXXX properties) and create their Actions.\n            TargetObjectType = typeof(Customers);\n        }\n        private FilterController standardFilterController;\n        protected override void OnActivated()\n        {\n            base.OnActivated();\n            standardFilterController = Frame.GetController\u003cFilterController\u003e();\n            if (standardFilterController != null)\n            {\n                \n                standardFilterController.CustomBuildCriteria += StandardFilterController_CustomBuildCriteria;\n            }\n        }\n\n        private void StandardFilterController_CustomBuildCriteria(object sender, CustomBuildCriteriaEventArgs e)\n        {\n            if (string.IsNullOrEmpty(e.SearchText))\n            {\n                e.Handled = false;\n                return;\n            }\n            \n            e.Criteria = CriteriaOperator.Parse($\"DoubleMetaphone('{e.SearchText}', [CompanyNameDoubleMetaphone]) or CharIndex('{e.SearchText}', [CompanyName]) \u003e -1\");\n            e.Handled = true;    \n        }\n\n        \n        protected override void OnDeactivated()\n        {\n            if (standardFilterController != null)\n            {\n                standardFilterController.CustomBuildCriteria -= StandardFilterController_CustomBuildCriteria;\n            }\n            base.OnDeactivated();\n        }\n    }\n```\n\nIn db Northwind add the field CompanyNameDoubleMetaphone in table Customers\n\n```\u003clanguage\u003e\nUSE [Northwind]\nGO\n\nSET ANSI_NULLS ON\nGO\n\nSET QUOTED_IDENTIFIER ON\nGO\n\nALTER TABLE Customers\nADD [CompanyNameDoubleMetaphone]  AS ([dbo].[udf_double_metaphone]([CompanyName])) PERSISTED\nGO\n```\n\n\nIn table customers I have added three similar strings (CompanyName field)\n\u003cpre\u003e'Blauer See    Delikatessen sa'\n'Blauer Se    Delikatessen s.a.'\n'Blaer Se    Deliktesse s.a.'\u003c/pre\u003e\n\nand for example I search for  ***'Blaer Se Delikatessen'*** then I match all strings\n\n![search](https://github.com/nicogis/DoubleMetaphoneXAF/blob/master/DoubleMetaphone/images/Search.png)\n\n\n\n\n\n\n\n     \n\n\n\n\n\n \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnicogis%2Fdoublemetaphonexaf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnicogis%2Fdoublemetaphonexaf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnicogis%2Fdoublemetaphonexaf/lists"}