如何创建实体框架可以转换为SQL查询的扩展方法?

时间:2019-05-22 07:35:01

标签: c# oracle entity-framework linq extension-methods

我正在网站上创建一个简单的搜索功能。搜索功能应该只在对象列表(IQueryable)的不同属性中寻找字符串。

对象来自使用实体框架的Oracle数据库表。

IQueryable<SupplierAddress> data = _dbContext.SupplierAddresses;

接下来,我们使用用户输入的searchString过滤此IQueryable:

    data = data.Where(d =>                                
    d.Supplier.Name.ToUpper().Contains(searchTerm.Trim()) || 
    d.Supplier.NameCleaned.ToUpper().Contains(searchTerm.Trim()) || 
    d.Supplier.NameShort.ToUpper().Contains(searchTerm.Trim()) ||   
    d.Supplier.NameShortCleaned.ToUpper().Contains(searchTerm.Trim()) ||
    d.Town.ToUpper().Contains(searchTerm.Trim()) ||   
    d.Country.Name.ToUpper().Contains(searchTerm.Trim());

现在,如您所见,我们使用.Trim()防止错误(此问题中提到的问题:ORA-01425: escape character must be character string of length 1)。由于这个错误,我们也无法在进行过滤之前修剪searchString。

我正在尝试创建一个扩展方法,该方法可以同时执行searchString的.Trim()和.Contains。此扩展方法应可由Entity Framework解释,并且应能够由EF转换为正确的SQL查询。

这是我当前的扩展方法:

public static class StringExtensions
{
    public static bool ContainsTrim(this string source, string toCheck)
    {
        return source.Contains(toCheck.Trim());
    }
}

但是当以这种方式使用它时,它无法成功地转换为SQL查询。

    data = data.Where(d =>                                
    d.Supplier.Name.ToUpper().ContainsTrim(searchTerm) || 
    d.Supplier.NameCleaned.ToUpper().ContainsTrim(searchTerm) || 
    d.Supplier.NameShort.ToUpper().ContainsTrim(searchTerm) ||   
    d.Supplier.NameShortCleaned.ToUpper().ContainsTrim(searchTerm) ||
    d.Town.ToUpper().ContainsTrim(searchTerm) ||   
    d.Country.Name.ToUpper().ContainsTrim(searchTerm));

我们收到以下错误:

System.NotSupportedException: 'LINQ to Entities does not recognize the 
method 'Boolean ContainsTrim(System.String, System.String)' method, and 
this method cannot be translated into a store expression.'

是否可以制作一个扩展方法,该方法既可以进行修整又可以被EF解释为包含?

我还看到了将表达式存储在变量中的内容(例如:Can I use an extension method in Entity Framework SubQuery?),这也可以解决我的问题,但是表达式需要能够接收参数(searchString)。

提前感谢您的时间和帮助。

0 个答案:

没有答案