我有以下代码段:
var a = dbContext.Employees.AsQueryable();
var b = dbContext.Employees.Where(x => x.IsManager == 1);
var results = dbContext.Companies
.SelectMany(x => x.IsActive == 1 ? a : b)
.Select(x => x.Id);
我认为它可以执行而没有任何问题,但是有趣的是我收到了这个错误:
失败:Microsoft.AspNetCore.Server.Kestrel [13] 连接ID“ 0HLQ6AD1S5ITB”,请求ID“ 0HLQ6AD1S5ITB:00000001”:应用程序引发了未处理的异常。 System.ArgumentException:参数类型不匹配 在System.Linq.Expressions.Expression.Condition处(表达式测试,表达式ifTrue,表达式ifFalse,类型type) 在System.Linq.Expressions.ConditionalExpression.Update处(表达式测试,表达式ifTrue,表达式ifFalse) 在System.Linq.Expressions.ExpressionVisitor.VisitConditional(ConditionalExpression节点) 在System.Linq.Expressions.ConditionalExpression.Accept(ExpressionVisitor访问者) 在System.Linq.Expressions.ExpressionVisitor.Visit(Expression节点) 在Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.ReplaceClauseReferences(表达式,IQuerySource查询源,布尔inProjection) 在Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.CompileAdditionalFromClauseExpression(AdditionalFromClause AdditionalFromClause,QueryModel queryModel) 在Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.CompileAdditionalFromClauseExpression(AdditionalFromClause AdditionalFromClause,QueryModel queryModel) 在Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitAdditionalFromClause(AdditionalFromClause fromClause,QueryModel queryModel,Int32索引) 在Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitAdditionalFromClause(AdditionalFromClause fromClause,QueryModel queryModel,Int32索引) 在Remotion.Linq.Clauses.AdditionalFromClause.Accept(IQueryModelVisitor访问者,QueryModel queryModel,Int32索引) 在Remotion.Linq.QueryModelVisitorBase.VisitBodyClauses(ObservableCollection`1 bodyClauses,QueryModel queryModel) 在Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel) 在Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitQueryModel(QueryModel queryModel) 在Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitQueryModel(QueryModel queryModel) 在Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.CreateQueryExecutor [TResult](QueryModel queryModel) 在Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery [TResult](QueryModel queryModel)
我不确定这里出了什么问题,尤其是该代码段可以正确显示结果吗?
var a = dbContext.Employees.AsQueryable();
var results = dbContext.Companies
.SelectMany(x => a)
.Select(x => x.Id);
这个单独的片段也可以正常工作:
var b = dbContext.Employees.Where(x => x.IsManager == 1);
var results = dbContext.Companies
.SelectMany(x => b)
.Select(x => x.Id);
P.S。我正在使用EF Core 2.2
更新1
好的,我试图通过上面的示例简化我的问题,但是我认为这不是一个好主意。
这就是我实际拥有的:我有三个主要实体:Post
,Employee
和WorkGroup
,以及三个映射实体:EmployeeWorkGroup
,{{1 }}和PostEmployee
。这六个实体具有以下实现:
PostWorkGroup
简单地说,主要目的是通过工作组(使用class Post {
public Guid Id { get; set; }
public int IsGlobal { get; set; }
public virtual ICollection<PostEmployee> Employees { get; set; }
public virtual ICollection<PostWorkGroup> WorkGroups { get; set; }
}
class Employee {
public Guid Id { get; set; }
}
class WorkGroup {
public Guid Id { get; set; }
public Guid? ParentId { get; set; }
public string Prefix { get; set; }
}
class EmployeeWorkGroup {
public Guid EmployeeId { get; set; }
public Guid WorkGroupId { get; set; }
public virtual Employee Employee { get; set }
public virtual WorkGroup WorkGroup { get; set; }
}
class PostEmployee {
public Guid EmployeeId { get; set; }
public Guid PostId { get; set; }
public virtual Employee Employee { get; set }
public virtual Post Post { get; set; }
}
class PostWorkGroup {
public Guid WorkGroupId { get; set; }
public Guid PostId { get; set; }
public virtual WorkGroup WorkGroup { get; set; }
public virtual Post Post { get; set; }
}
和PostEmployee
)直接向员工发送帖子(使用EmployeeWorkGroup
实体),或者所有员工(将PostWorkGroup
中的IsGlobal
设置为1)。
我设法完成了上述操作,现在我想获取给定职位的员工。面临的挑战是,我需要从职位的指定工作组(使用Post
和EmployeeWorkGroup
到职位的指定工作组(以及使用PostWorkGroup
实体的员工)中收集它们。如果帖子发给每个人(即PostEmployee
为1),我需要退回所有员工。
这是我目前的尝试
IsGlobal
在没有条件的情况下,我可以完美地执行if-else的任何一侧。
P.S。我正在使用LinqKit。
更新2
这是我通过执行上面的代码而获得的查询(我删除了if的一侧以使其工作):
// get all employee ids from the posts work groups
Expression<Func<Post, IEnumerable<Guid>>> postEmployeesFromWorkGroups = post =>
allWorkGroups
.Where(workGroup => post.WorkGroups
.Any(postWorkGroup => workGroup.Prefix.StartsWith(postWorkGroup.WorkGroup.Prefix)))
.SelectMany(y => y.Employees
.Where(z => !post.Employees.Any(b => b.EmployeeId.Equals(z.EmployeeId))))
.Select(y => y.EmployeeId)
.Distinct();
// get all employee ids from posts' immediate employees list
Expression<Func<Post, IEnumerable<Guid>>> postEmployees = post => post.Employees.Select(x => x.EmployeeId);
// return the results
public static Expression<Func<Post, IEnumerable<Employee>>> var predicate = post => post.IsGlobal == 1
? allEmployees
: allEmployees.Where(x =>
postEmployeesFromWorkGroups.Invoke(post).Contains(x.Id) ||
postEmployees.Invoke(post).Contains(x.Id));
db.Posts.AsExpandable().Where(x=>x.Id.Equals("some-id")).Select(predicate);