请。有人可以解释如何使用valueobject查询ef core吗?
即FirstOrDefault(d => d.Email == "john@corp.com") translates to WHERE =
FirstOrDefault(d => d.Email.Value.Contains("corp.com")) fails LINQ expression could not be translated
(按预期)。
如果Email属性只是简单的字符串原始类型
FirstOrDefault(d => d.Email.Contains("corp.com")) translates to CHARINDEX(N'corp.com', Email) > 0
解决方法似乎是
.FirstOrDefault(d => EF.Functions.Like(d.Email, "%corp.com%")); translates to LIKE
,但是这种解决方法强制在项目上使用Microsoft.EntityFrameworkCore
我想在没有这种限制的情况下使用“包含”或“喜欢”。
在一次“绝望”尝试中,我尝试使用下面的反编译代码来模仿EF.Functions.Like。
但仅适用于InMemory提供程序。
对于SqlServer提供程序失败,...通过插入对AsEnumerable()的调用,LINQ表达式无法转换为显式切换到客户端评估
只是为了好玩..下面的“模仿”代码。
public static class DbFunctionsExtensions
{
public static bool Like(string matchExpression, string pattern) => LikeCore(matchExpression, pattern, escapeCharacter: null);
public static bool Like(string matchExpression, string pattern, string escapeCharacter) => LikeCore(matchExpression, pattern, escapeCharacter);
private static readonly char[] _regexSpecialChars = { '.', '$', '^', '{', '[', '(', '|', ')', '*', '+', '?', '\\' };
private static readonly string _defaultEscapeRegexCharsPattern = BuildEscapeRegexCharsPattern(_regexSpecialChars);
private static readonly TimeSpan _regexTimeout = TimeSpan.FromMilliseconds(value: 1000.0);
private static string BuildEscapeRegexCharsPattern(IEnumerable<char> regexSpecialChars) => string.Join("|", regexSpecialChars.Select(c => @"\" + c));
private static bool LikeCore(string matchExpression, string pattern, string escapeCharacter)
{
var singleEscapeCharacter = string.IsNullOrEmpty(escapeCharacter) ? (char?)null : escapeCharacter.First();
if (matchExpression == null || pattern == null) return false;
if (matchExpression.Equals(pattern, StringComparison.OrdinalIgnoreCase)) return true;
if (matchExpression.Length == 0 || pattern.Length == 0) return false;
var escapeRegexCharsPattern = singleEscapeCharacter == null ? _defaultEscapeRegexCharsPattern : BuildEscapeRegexCharsPattern(_regexSpecialChars.Where(c => c != singleEscapeCharacter));
var regexPattern = Regex.Replace(pattern, escapeRegexCharsPattern, c => @"\" + c, default, _regexTimeout);
var stringBuilder = new StringBuilder();
for (var i = 0; i < regexPattern.Length; i++)
{
var c = regexPattern[i];
var escaped = i > 0 && regexPattern[i - 1] == singleEscapeCharacter;
switch (c)
{
case '_':
{
stringBuilder.Append(escaped ? '_' : '.');
break;
}
case '%':
{
stringBuilder.Append(escaped ? "%" : ".*");
break;
}
default:
{
if (c != singleEscapeCharacter) stringBuilder.Append(c);
break;
}
}
}
regexPattern = stringBuilder.ToString();
return Regex.IsMatch(matchExpression, @"\A" + regexPattern + @"\s*\z", RegexOptions.IgnoreCase | RegexOptions.Singleline, _regexTimeout);
}
}