ef核心查询ValueObjects

时间:2020-05-25 09:37:12

标签: entity-framework linq domain-driven-design

请。有人可以解释如何使用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);
    }
}

0 个答案:

没有答案