EntityFramework 6.4.4 - 如何将集合投影到实现 IEnumerable<T> 的自定义对象?
EntityFramework 6.4.4 - How to project collection to a custom object implementing IEnumerable<T>?
无法映射到实现 IEnumerable 的自定义对象?
public class BranchCollection : IEnumerable<int>
{
public IEnumerable<int> BranchIds { get; set; } = new List<int>();
public BranchPermission() { }
//Custom Code here
}
public class UserDto {
public BranchCollection Collection { get; set; }
}
正在尝试使用以下代码投影到 UserDto
dbContext.Users.Select(
x => new UserDto {
Collection = new BranchCollection { BranchIds = x.Branches.Select(y => y.BranchId) }
}
.ToList();
异常
A type that implements IEnumerable 'BranchCollection' cannot be initialized in a LINQ to Entities query.
堆栈跟踪
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.CheckInitializerType(Type type)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MemberInitTranslator.TypedTranslate(ExpressionConverter parent, MemberInitExpression linq)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MemberInitTranslator.TypedTranslate(ExpressionConverter parent, MemberInitExpression linq)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SelectTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.Convert()
at System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable1 forMergeOption) at System.Data.Entity.Core.Objects.ObjectQuery
1.<>c__DisplayClass41_0.b__1()
at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess) at System.Data.Entity.Core.Objects.ObjectQuery
1.<>c__DisplayClass41_0.b__0()
at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func1 operation) at System.Data.Entity.Core.Objects.ObjectQuery
1.GetResults(Nullable1 forMergeOption) at System.Data.Entity.Core.Objects.ObjectQuery
1.<System.Collections.Generic.IEnumerable.GetEnumerator>b__31_0()
at System.Data.Entity.Internal.LazyEnumerator1.MoveNext() at System.Collections.Generic.List
1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable
1 source)
EF 不能 understand/initiate 那 class。它旨在适应简单 classes 和集合的投影。如果你觉得你必须这样做,那么 double-project:
var userDetails dbContext.Users.Select(x => new
{
BranchIds = x.Branches.Select(b => b.BranchId).ToList()
}).ToList() // This executes the query getting our branch IDs (and include anything from the User we need as well.
.Select(x => new UserDto
{
Collection = new BranchCollection { BranchIds = x.BranchIds }
}.ToList(); // Project to your custom type from memory.
对于 class 这样的你想要包装 IEnumerable
的地方,我建议将源集合传递到构造函数中以初始化私有成员并使其不可变,公开你的枚举器等。如果项目可以是 added/removed 然后用你的 class 中的方法来适应它,而不是公开一个包含的集合,以后任何人都可以写
userDto.Collection = new BranchCollection();
...并且可能会搞砸。
无法映射到实现 IEnumerable 的自定义对象?
public class BranchCollection : IEnumerable<int>
{
public IEnumerable<int> BranchIds { get; set; } = new List<int>();
public BranchPermission() { }
//Custom Code here
}
public class UserDto {
public BranchCollection Collection { get; set; }
}
正在尝试使用以下代码投影到 UserDto
dbContext.Users.Select(
x => new UserDto {
Collection = new BranchCollection { BranchIds = x.Branches.Select(y => y.BranchId) }
}
.ToList();
异常
A type that implements IEnumerable 'BranchCollection' cannot be initialized in a LINQ to Entities query.
堆栈跟踪
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.CheckInitializerType(Type type) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MemberInitTranslator.TypedTranslate(ExpressionConverter parent, MemberInitExpression linq) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MemberInitTranslator.TypedTranslate(ExpressionConverter parent, MemberInitExpression linq) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SelectTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.Convert() at System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable
1 forMergeOption) at System.Data.Entity.Core.Objects.ObjectQuery
1.<>c__DisplayClass41_0.b__1() at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess) at System.Data.Entity.Core.Objects.ObjectQuery
1.<>c__DisplayClass41_0.b__0() at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func1 operation) at System.Data.Entity.Core.Objects.ObjectQuery
1.GetResults(Nullable1 forMergeOption) at System.Data.Entity.Core.Objects.ObjectQuery
1.<System.Collections.Generic.IEnumerable.GetEnumerator>b__31_0() at System.Data.Entity.Internal.LazyEnumerator1.MoveNext() at System.Collections.Generic.List
1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable
1 source)
EF 不能 understand/initiate 那 class。它旨在适应简单 classes 和集合的投影。如果你觉得你必须这样做,那么 double-project:
var userDetails dbContext.Users.Select(x => new
{
BranchIds = x.Branches.Select(b => b.BranchId).ToList()
}).ToList() // This executes the query getting our branch IDs (and include anything from the User we need as well.
.Select(x => new UserDto
{
Collection = new BranchCollection { BranchIds = x.BranchIds }
}.ToList(); // Project to your custom type from memory.
对于 class 这样的你想要包装 IEnumerable
的地方,我建议将源集合传递到构造函数中以初始化私有成员并使其不可变,公开你的枚举器等。如果项目可以是 added/removed 然后用你的 class 中的方法来适应它,而不是公开一个包含的集合,以后任何人都可以写
userDto.Collection = new BranchCollection();
...并且可能会搞砸。