Entity Framework Core 6 - 通过命令拦截修剪所有返回的字符串

问题描述 投票:0回答:1

当我使用 EF (System.Data.Entity) 时,我成功地使用了一个拦截器来自动修剪数据库中所有现有的字符串。
IDbCommandTreeInterceptor 在这篇文章中进行了描述:EF6.1 – 解决字符串连接中的尾随空白问题.

    public class StringTrimmerInterceptor : IDbCommandTreeInterceptor
    {
        public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext)
        {
            if (interceptionContext.OriginalResult.DataSpace == DataSpace.SSpace)
            {
                var queryCommand = interceptionContext.Result as DbQueryCommandTree;
                if (queryCommand != null)
                {
                    var newQuery = queryCommand.Query.Accept(new StringTrimmerQueryVisitor());
                    interceptionContext.Result = new DbQueryCommandTree(
                        queryCommand.MetadataWorkspace,
                        queryCommand.DataSpace,
                        newQuery);
                }
            }
        }

        private class StringTrimmerQueryVisitor : DefaultExpressionVisitor
        {
            private static readonly string[] _typesToTrim = { "nvarchar", "varchar", "char", "nchar" };

            public override DbExpression Visit(DbNewInstanceExpression expression)
            {
                var arguments = expression.Arguments.Select(a =>
                {
                    var propertyArg = a as DbPropertyExpression;
                    if (propertyArg != null && _typesToTrim.Contains(propertyArg.Property.TypeUsage.EdmType.Name))
                        return EdmFunctions.Trim(a);

                    return a;
                });

                return DbExpressionBuilder.New(expression.ResultType, arguments);
            }
        }
    }

我需要一些帮助来通过 EntityFrameworkCore DbCommandInterceptor 实现相同的功能。

string entity-framework-core .net-6.0 interceptor trim
1个回答
0
投票

最后我不得不自己找到解决方案。
首先,我通过以下方式实现了抽象类DbDataReader

    public class TrimStringsDataReader : DbDataReader
    {
        private readonly DbDataReader _innerReader;

        public TrimStringsDataReader(DbDataReader innerReader)
        {
            _innerReader = innerReader;
        }

        public override string GetString(int ordinal)
        {
            var value = _innerReader.GetString(ordinal);
    #pragma warning disable CS8603 // Possible null reference return.
            return value?.Trim();
    #pragma warning restore CS8603 // Possible null reference return.
        }

        public override object GetValue(int ordinal)
        {
            var value = _innerReader.GetValue(ordinal);
            if (value is string stringValue)
                value = stringValue.Trim();
            return value;
        }

        public override object this[int ordinal] => _innerReader[ordinal];

        public override object this[string name] => _innerReader[name];

        public override int Depth => _innerReader.Depth;

        public override int FieldCount => _innerReader.FieldCount;

        public override bool HasRows => _innerReader.HasRows;

        public override bool IsClosed => _innerReader.IsClosed;

        public override int RecordsAffected => _innerReader.RecordsAffected;

        public override bool GetBoolean(int ordinal) => _innerReader.GetBoolean(ordinal);
        // And so on all the other methods
    }

然后我覆盖了DbCommandInterceptor类:

    public class TrimStringsInterceptor : DbCommandInterceptor
    {
        public override DbDataReader ReaderExecuted(
            DbCommand command,
            CommandExecutedEventData eventData,
            DbDataReader result)
        {
            result = new TrimStringsDataReader(result);
            return base.ReaderExecuted(command, eventData, result);
        }

        public override ValueTask<DbDataReader> ReaderExecutedAsync(
            DbCommand command,
            CommandExecutedEventData eventData,
            DbDataReader result,
            CancellationToken cancellationToken = default)
        {
            result = new TrimStringsDataReader(result);
            return base.ReaderExecutedAsync(command, eventData, result, cancellationToken);
        }
    }

以这种方式,EF Core 实例化传递给 ReaderExecuted/Async 的 DbDataReader 具体类(它取决于驱动程序,即在 SqlServer 的情况下是 Microsoft.Data.SqlClient.SqlDataReader),因此我可以使用真正的阅读器“装饰“用我的修剪字符串行为。

© www.soinside.com 2019 - 2024. All rights reserved.