我正在使用一个帮助器类来构建一个表达式,然后将该表达式传递给EF Core .Select()
上的DbSet
调用,以便我可以从数据库中动态选择字段并忽略大字段我不在乎的。
助手类如下:
public static class ExpressionHelper
{
public static Expression<Func<T, T>> BuildFieldSelector<T>(IEnumerable<string> fields)
{
// input parameter "x"
var param = Expression.Parameter(typeof(T), "x");
// new statement "new Data()"
var newExpression = Expression.New(typeof(T));
// create initializers
var bindings = fields
.Select(x => {
// property "Field1"
var property = typeof(T).GetProperty(x.Trim(), BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
if (property == null)
return null;
// original value "x.Field1"
var memberExpression = Expression.Property(param, property);
// set value "Field1 = x.Field1"
return Expression.Bind(property, memberExpression);
})
.Where(x => x != null);
// initialization "new Data { Field1 = x.Field1, Field2 = x.Field2 }"
var memberInit = Expression.MemberInit(newExpression, bindings);
// expression "x => new Data { Field1 = x.Field1, Field2 = x.Field2 }"
return Expression.Lambda<Func<T, T>>(memberInit, param);
}
}
正如我所说的,生成的表达式被传递给EF DbSet上的.Select()
LINQ调用。
一切正常,但我现在遇到以下异常:
No coercion operator is defined between types 'System.Int16' and 'System.Boolean'.
at System.Linq.Expressions.Expression.GetUserDefinedCoercionOrThrow(ExpressionType coercionType, Expression expression, Type convertToType)
at System.Linq.Expressions.Expression.Convert(Expression expression, Type type, MethodInfo method)
at System.Linq.Expressions.Expression.Convert(Expression expression, Type type)
at Microsoft.EntityFrameworkCore.Storage.TypedRelationalValueBufferFactoryFactory.CreateGetValueExpression(Expression dataReaderExpression, Expression indexExpression, TypeMaterializationInfo materializationInfo, Boolean box)
at Microsoft.EntityFrameworkCore.Storage.TypedRelationalValueBufferFactoryFactory.<>c.<CreateArrayInitializer>b__12_0(TypeMaterializationInfo mi, Int32 i)
at System.Linq.Enumerable.SelectIterator[TSource,TResult](IEnumerable`1 source, Func`3 selector)+MoveNext()
at System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1 items)
at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at System.Dynamic.Utils.CollectionExtensions.ToReadOnly[T](IEnumerable`1 enumerable)
at System.Linq.Expressions.Expression.NewArrayInit(Type type, IEnumerable`1 initializers)
at Microsoft.EntityFrameworkCore.Storage.TypedRelationalValueBufferFactoryFactory.CreateArrayInitializer(CacheKey cacheKey)
at Microsoft.EntityFrameworkCore.Storage.TypedRelationalValueBufferFactoryFactory.<Create>b__10_0(CacheKey k)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Microsoft.EntityFrameworkCore.Storage.TypedRelationalValueBufferFactoryFactory.Create(IReadOnlyList`1 types)
at Microsoft.EntityFrameworkCore.Query.Sql.DefaultQuerySqlGenerator.CreateValueBufferFactory(IRelationalValueBufferFactoryFactory relationalValueBufferFactoryFactory, DbDataReader dataReader)
at Microsoft.EntityFrameworkCore.Query.Internal.ShaperCommandContext.<NotifyReaderCreated>b__14_0(FactoryAndReader s)
at Microsoft.EntityFrameworkCore.Internal.NonCapturingLazyInitializer.EnsureInitialized[TParam,TValue](TValue& target, TParam param, Func`2 valueFactory)
at Microsoft.EntityFrameworkCore.Query.Internal.ShaperCommandContext.NotifyReaderCreated(DbDataReader dataReader)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.BufferlessMoveNext(DbContext _, Boolean buffer)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()
at System.Collections.Generic.List`1.AddEnumerable(IEnumerable`1 enumerable)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at TAP.Services.TourManagementService.GetReviews(String tourId, IEnumerable`1 fields) in C:\Projects\TheAdventurePeople\TAP.Services\TAP.Services\Services\TourManagementService.cs:line 322
自从工作以来,我根本没有更改过代码,因此我不确定是什么原因造成的。我也没有更改用于表达式的模型类中的任何类型。在此实例中正在构建的表达式如下所示:
{x => new TourReview() {ReviewId = x.ReviewId, TourId = x.TourId, Score = x.Score, ReviewerName = x.ReviewerName, IsHidden = x.IsHidden}}
和TourReview类如下:
public class TourReview
{
public int ReviewId { get; set; }
[Required]
public string TourId { get; set; }
[Required]
[DataType(DataType.Date)]
[Display(Name = "Review Date")]
public DateTime DateReviewed { get; set; }
[Required]
public decimal Score { get; set; }
public string Title { get; set; }
[Required]
[Display(Name = "Review Text")]
public string Text { get; set; }
[Required]
[Display(Name = "Reviewer Name")]
public string ReviewerName { get; set; }
public bool IsHidden { get; set; }
}
我最近确实从5.7升级到了.NET Core 2.1和MySQL 8.0.13,
编辑: 我还记得最近我已经从Pomelo MySQL连接器更改为官方的MySQL.Data.EntityFrameworkCore连接器。
编辑2:
我相信这是在我对本地计算机上的MySQL Server进行升级之后开始发生的。新版本似乎导致类型映射出现问题。将.Property(x => x.IsHidden).HasConversion(x => Convert.ToInt32(x), x => Convert.ToBoolean(x));
添加到模型构建器可以解决此问题,但我不想对我拥有的每个布尔属性都执行此操作!