我必须在SQL中匹配带有最小/最大范围的邮政编码的记录
挑战在于数据质量很差,一些邮政编码不仅仅是数字
所以我试着匹配"好的邮政编码">通过丢弃坏的或者甚至只保留数字
- 我不知道如何使用Regex.Replace(…)@" [^ d]",")而不是Regex.Match(…, @"d")以适应下面的查询
- 我得到一个错误的代码在运行时
我试着
- 正则表达式。IsMatch
- SqlFunctions。IsNumeric
它们都会在运行时导致错误,下面是代码:
var data = context.Leads.AsQueryable();
data = data.Include(p => p.Company).Include(p => p.Contact);
data = data.Where(p => Regex.IsMatch(p.Company.ZipCode, @"d"));
data = data.Where(p => Convert.ToInt32(p.Company.ZipCode) >= range.Min);
data = data.Where(p => Convert.ToInt32(p.Company.ZipCode) <= range.Max);
错误如下:
System.InvalidOperationException: The LINQ expression 'DbSet<Lead>
.Join(
outer: DbSet<Company>,
inner: l => EF.Property<Nullable<int>>(l, "CompanyId"),
outerKeySelector: c => EF.Property<Nullable<int>>(c, "Id"),
innerKeySelector: (o, i) => new TransparentIdentifier<Lead, Company>(
Outer = o,
Inner = i
))
.Where(l => !(Regex.IsMatch(
input: l.Inner.ZipCode,
pattern: "d")))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync().
我不知道如何解决这个问题。我真的不明白AsEnumerable()、AsAsyncEnumerable()、ToList()或ToListAsync()在这里有什么帮助
我做错了什么?
谢谢你的帮助
我试了所有能想到的
各种各样的linq/ef技巧,我甚至试图定义一个从未找到的DBFunction
一旦我有了一个直接用SQL编写的正在运行的存储过程,我最终得到了一个列表,而不是一个IQueryable,所以我回到了#1
最后,我在表中创建了一个新字段:
ZipCodeNum
保存邮政编码字符串
的过滤转换版本。当你使用可查询列表时,EF Core 5总是试图将查询转换为SQL,所以你必须使用SQL Server可以理解的代码。如果你想使用c#函数,你必须先使用ToList()
或ToArray()
下载数据到服务器,然后你可以使用下载的数据使用任何c#函数。
你可以尝试这样做:
var data = context.Leads
.Include(p => p.Company)
.Include(p => p.Contact)
.Where(p =>
p.Company.Zipcode.All(char.IsDigit)
&& (Convert.ToInt32(p.Company.ZipCode) >= range.Min) //or >=1
&& ( Convert.ToInt32(p.Company.ZipCode) <= range.Max) ) // or <=99999
.ToArray();