关于“LINQ to Entities does not recognize the Method '...' ”问题原因浅析

LINQ to Entities 中,有些断言能对内存实体使用,但是发到数据库端可能因无法解析而抛出异常,需要特别注意。示例如下:

s.IsNullOrWhiteSpace(), s.IsNullOrEmpty, s.IsEmpty()(这些方法都属于自定义的扩展方法,无法被EF直接解析为SQL语句)
如 a => a.FullName.IsNullOrWhiteSpace() 可以改写为: a => a.FullName != null && a.FullName.Length > 0
        [TestMethod]
        public void DataSourceGetOneTest()
        {
            string host = "localHost";
            IList<string> IpAddress = EnvironmentEx.GetIpAddress();
            ServerContext sc = this.CreateServerContext();
            using (EdmWcfService edm = sc.CreateEdm<EdmWcfService>(Dbs.His))
            {
                // a => string.Equals(a.Name, host, StringComparison.CurrentCultureIgnoreCase不能用于数据库端,否则报下面错误:
                // System.ArgumentException:“为方法“Boolean Equals(System.String, System.String, System.StringComparison)”的调用提供的参数的数量不正确”
                // var dto = edm.WcfServers.FirstOrDefault(a => string.Equals(a.Name, host, StringComparison.CurrentCultureIgnoreCase));

                // 如下用法是正确的:
                var dto = edm.WcfServers.FirstOrDefault(a => (a.Name != null && a.Name.Equals(host, StringComparison.CurrentCultureIgnoreCase))
                                          || (a.Name != null && a.FullName.Equals(host, StringComparison.CurrentCultureIgnoreCase)));
                // 下面写法也会报错如下:
                // LINQ to Entities does not recognize the method 'Boolean StartsWith(System.String, System.StringComparison)' method, and this method cannot be translated into a store expression.
                //dto = edm.WcfServers.FirstOrDefault(a => (a.Name != null && a.Name.StartsWith(host, StringComparison.CurrentCultureIgnoreCase))
                //                          || (a.Name != null && a.FullName.StartsWith(host, StringComparison.CurrentCultureIgnoreCase)));

                // 如下用法是正确的:
                dto = edm.WcfServers.FirstOrDefault(a => (a.Name != null && a.Name.ToUpper().StartsWith(host.ToUpper()))
                                          || (a.Name != null && a.FullName.ToUpper().StartsWith(host.ToUpper())));

                int serverId = (dto != null) ? dto.ServerId : -1;
                Assert.IsTrue(serverId > 0);
            }

        }

其次,ORACLE数据库中空字符串被视为NULL处理,因此数据库SQL函数中字段值为' '(空格)的被 RTRIM(LRTRIM(a.Name)) 调用后结果并非空字符串,而是NULL。所以需要注意:

    [TestMethod()]
    public void TestEdmQuery()
    {
        using (ServerContext sc = WcfServiceHelper.CreateServerContext(ClientContext.Instance))
        {
            using (EdmConfig edm = sc.CreateEdm<EdmConfig>(Dbs.His))
            {
                var query = edm.EntityPickers.Where(a => a.UseCaseKey != null && a.UseCaseKey.Trim() == null);
                string tracestring = query.ToTraceString();
                Debug.Print(tracestring);
                IList<DtoEntityPicker> ret = query.ToList();
            }
        }
    }

 

posted @ 2024-04-03 15:48  Chr☆s  阅读(33)  评论(0编辑  收藏  举报