Как я могу настроить Entity Framework для автоматической подстройки значений, полученных для определенных столбцов, сопоставленных полям char (N)?

.net entity-framework entity-framework-6 sql trim

Вопрос

Я работаю с сторонней базой данных, в которой все текстовые значения хранятся как char(n) . Некоторые из этих текстовых значений являются первичными ключами, тогда как другие являются обычным для человека понятным текстом. Для последнего я хочу, чтобы полученные значения были автоматически обрезаны.

Я знаю, что могу добавить Trim для всех запросов LINQ to Entities, но это грязно, ненадежно и ненадежно. Я хотел бы как-то настроить Entity Framework для автоматической подстройки значений, полученных из определенных столбцов.

Однако я не знаю, как это сделать. Я использую свободный API EF. Самое близкое, о чем я думал до сих пор, это создание дополнительных свойств для обертывания реальных свойств с помощью вызовов метода Trim , но это грязно и все еще не очень удобно. Я также предпочел бы, чтобы обрезка выполнялась в базе данных, а не в приложении.

Популярные ответы

Роуэн Миллер (менеджер программ для Entity Framework в Microsoft) недавно опубликовала хорошее решение для этого, которое использует Interceptors. По общему признанию, это справедливо только в EF 6.1+. Его сообщение посвящено завершающим строкам в соединениях, но в основном решение, применяемое, аккуратно удаляет завершающие строки из всех свойств строки в ваших моделях автоматически без заметного влияния на производительность.

Исходное сообщение в блоге: работа над завершающими пробелами в строковых объединениях

Соответствующий код переиздается здесь, но я рекомендую вам прочитать его сообщение в блоге. (Также, если вы используете EF, вы должны прочитать его блог в любом случае).

using System.Data.Entity.Core.Common.CommandTrees;
using System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder;
using System.Data.Entity.Core.Metadata.Edm;
using System.Data.Entity.Infrastructure.Interception;
using System.Linq;

namespace FixedLengthDemo
{
    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);
            }
        }
    }
}

Rowan продолжает: «Теперь, когда у нас есть перехватчик, нам нужно сказать EF, чтобы использовать его. Это лучше всего сделать с помощью Code-Based Configuration. Мы можем просто отказаться от следующего класса в той же сборке / проекте, что и наш контекст, и EF выберет это.

using System.Data.Entity.Core.Common.CommandTrees;
using System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder;
using System.Data.Entity.Core.Metadata.Edm;
using System.Data.Entity.Infrastructure.Interception;
using System.Linq;

namespace FixedLengthDemo
{
    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);
            }
        }
    }
}



Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему