使用Entity Framework 5在SQL Server中连接字符串和数字的最佳方法?

出于某种原因,微软决定不支持EF5中的简单连接。

例如

Select(foo => new { someProp = "hello" + foo.id + "/" + foo.bar } 

如果foo.id或foo.bar是数字,这将抛出。

我发现的解决方法显然是代码:

 Select(foo => new { someProp = "hello" + SqlFunctions.StringConvert((double?)foo.id).Trim() + "/" + SqlFunctions.StringConvert((double?)foo.bar).Trim() } 

哪个工作正常,但看起来很可怕。

那么,有更好的方法来实现这个更清洁的代码吗? 我对这个客户端不感兴趣,所以没有.AsEnumerable()请回答。

对于那些感兴趣。 我对这个function的缺乏感到很生气,我自己使用ExpressionVisitor实现了这个function。

您现在可以编写原始问题中的代码。

 using System; using System.Collections; using System.Collections.Generic; using System.Data.Objects.SqlClient; using System.Linq; using System.Linq.Expressions; namespace Crawlr.Web.Code { public static class ObjectSetExExtensions { public static ObjectSetEx Extend(this IQueryable self) where T : class { return new ObjectSetEx(self); } } public class ObjectSetEx : IOrderedQueryable { private readonly QueryProviderEx provider; private readonly IQueryable source; public ObjectSetEx(IQueryable source) { this.source = source; provider = new QueryProviderEx(this.source.Provider); } #region IQueryableEx Members public IEnumerator GetEnumerator() { return source.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return source.GetEnumerator(); } public Type ElementType { get { return source.ElementType; } } public Expression Expression { get { return source.Expression; } } public IQueryProvider Provider { get { return provider; } } #endregion } public class QueryProviderEx : IQueryProvider { private readonly IQueryProvider source; public QueryProviderEx(IQueryProvider source) { this.source = source; } #region IQueryProvider Members public IQueryable CreateQuery(Expression expression) { Expression newExpression = ExpressionReWriterVisitor.Default.Visit(expression); IQueryable query = source.CreateQuery(newExpression); return new ObjectSetEx(query); } public IQueryable CreateQuery(Expression expression) { Expression newExpression = ExpressionReWriterVisitor.Default.Visit(expression); IQueryable query = source.CreateQuery(newExpression); return query; } public TResult Execute(Expression expression) { Expression newExpression = ExpressionReWriterVisitor.Default.Visit(expression); return source.Execute(newExpression); } public object Execute(Expression expression) { Expression newExpression = ExpressionReWriterVisitor.Default.Visit(expression); return source.Execute(newExpression); } #endregion } public class ExpressionReWriterVisitor : ExpressionVisitor { public static readonly ExpressionReWriterVisitor Default = new ExpressionReWriterVisitor(); protected override Expression VisitUnary(UnaryExpression node) { if (node.NodeType == ExpressionType.Convert && node.Operand.Type == typeof(int) && node.Type==typeof(object)) { var operand = node.Operand; var stringConvertMethod = typeof(SqlFunctions).GetMethod("StringConvert", new Type[] { typeof(double?) }); var trimMethod = typeof(string).GetMethod("Trim",new Type[] {}); var dOperand = Expression.Convert(operand, typeof(double?)); return Expression.Call(Expression.Call(stringConvertMethod, dOperand),trimMethod); } return base.VisitUnary(node); } } } 

用法:

  var res = model .FooSet .Extend() //<- applies the magic .Select(foo => new { someProp = "hello" + foo.id + "/" + foo.bar }