我正在使用第三方数据库,其中所有文本值都存储为char(n)。这些文本值中的一些是主键,而其他的只是正常的人类可读文本。对于后者,我想要检索的值被自动修剪。 我知道我可以将
我知道我可以将Trim添加到我所有的LINQ to Entities查询中,但这是凌乱的,不可靠的和不可维护的。我想以某种方式配置Entity Framework来自动修剪从特定列中检索的值。
但是,我不知道该怎么做。我使用EF流畅的API。到目前为止,我所想到的最接近的事情是创建其他属性来使用Trim方法调用来包装实际的属性,但是这是一个凌乱而且仍然不是很可维护。我也希望在数据库中进行修整,而不是应用程序。
Rowan Miller(微软实体框架项目经理)最近发布了一个使用拦截器的很好的解决方案。诚然,这仅适用于EF 6.1。他的帖子是关于连接中的尾随字符串,但是基本上,应用的解决方案整体地自动地从模型中的所有字符串属性中删除尾随的字符串,而不会明显地影响性能。原创博客:Working around trailing blanks issue in string joins
相关代码在这里转贴,但我鼓励您阅读他的博文。 (另外如果你使用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来使用它,这最好是通过基于代码的配置完成,我们可以把下面的类放在与我们的上下文相同的程序集/项目中,而EF会选择它了“。
using System.Data.Entity;
namespace FixedLengthDemo
{
public class MyConfiguration : DbConfiguration
{
public MyConfiguration()
{
AddInterceptor(new StringTrimmerInterceptor());
}
}
}
