- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我需要多次检查相同的特定条件(where
子句):
return _ctx.Projects.Where(p => p.CompanyId == companyId &&
(p.Type == Enums.ProjectType.Open ||
p.Invites.Any(i => i.InviteeId == userId))).ToList()
'&&'之后的部分将导致用户无法检索受限项目。
我想将此检查抽象为一个函数。将来这些条件可能会改变,我不想替换所有的 LINQ 查询。
我使用以下扩展方法做到了这一点:
public static IQueryable<Project> IsVisibleForResearcher(this IQueryable<Project> projects, string userId)
{
return projects.Where(p => p.Type == Enums.ProjectType.Open ||
p.Invites.Any(i => i.InviteeId == userId));
}
现在我可以将 LINQ 查询更改为:
return _ctx.Projects.Where(p => p.CompanyId == companyId)
.IsVisibleForResearcher(userId).ToList()
这会生成相同的 SQL 查询。现在,当我想在另一个具有项目的 DbSet 上使用此扩展方法时,我的问题就出现了。
假设一家公司有项目。而我只想检索用户至少可以看到一个项目的公司。
return _ctx.Companies
.Where(c => c.Projects.Where(p =>
p.Type == Enums.ProjectType.Open ||
p.Invites.Any(i => i.InviteeId == userId))
.Any())
这里我也喜欢用扩展的方式。
return _ctx.Companies
.Where(c => c.Projects.AsQueryable().IsVisibleForCompanyAccount(userId).Any())
这会抛出以下异常:
An exception of type 'System.NotSupportedException' occurred in Remotion.Linq.dll but was not handled in user code
Additional information: Could not parse expression 'c.Projects.AsQueryable()': This overload of the method 'System.Linq.Queryable.AsQueryable' is currently not supported.
我创建了以下扩展方法:
public static IEnumerable<Project> IsVisibleForResearcher(this ICollection<Project> projects, string userId)
{
return projects.Where(p => p.Type == Enums.ProjectType.Open ||
p.Invites.Any(i => i.InviteeId == userId));
}
但这也不起作用。
有人有想法吗?或朝着正确方向迈出的一步。
顺便说一句,我在 .NET Core 上使用 Entity Framework Core
更新:
使用 Expression<Func<>>
导致相同的异常:
'System.Linq.Queryable.AsQueryable' is currently not supported.
更新 2
感谢@ivan-stoev 提供了解决方案。我还有一个问题。我还想检索“可见”项目的数量。
我通过这样做修复了它:
var companies = _ctx.Companies
.WhereAny(c => c.Projects, Project.IsProjectVisibleForResearcher(userId))
.Select(c => new CompanyListDto
{
Id = c.Id,
Name = c.Name,
LogoId = c.LogoId,
ProjectCount = _ctx.Projects.Where(p => p.CompanyId == c.Id)
.Count(Project.IsProjectVisibleForResearcher(userId))
});
但我找不到只使用 c.Projects
的方法而不是 ctx.Projects.Where(p => p.CompanyId == c.Id)
生成的 SQL 是正确的,但我想避免这种不必要的检查。
真诚的,布莱希特
最佳答案
在 IQueryable<T>
中使用表达式/自定义方法查询表达式一直存在问题,需要一些表达式树后处理。例如,LinqKit提供 AsExpandable
, Invoke
和 Expand
为此目的自定义扩展方法。
虽然不那么笼统,但这里是不使用第 3 方包的示例用例的解决方案。
首先,提取一个方法中谓词的表达式部分。 IMO 的逻辑位置是 Project
类:
public class Project
{
// ...
public static Expression<Func<Project, bool>> IsVisibleForResearcher(string userId)
{
return p => p.Type == Enums.ProjectType.Open ||
p.Invites.Any(i => i.InviteeId == userId);
}
}
然后,像这样创建一个自定义扩展方法:
public static class QueryableExtensions
{
public static IQueryable<T> WhereAny<T, E>(this IQueryable<T> source, Expression<Func<T, IEnumerable<E>>> elements, Expression<Func<E, bool>> predicate)
{
var body = Expression.Call(
typeof(Enumerable), "Any", new Type[] { typeof(E) },
elements.Body, predicate);
return source.Where(Expression.Lambda<Func<T, bool>>(body, elements.Parameters));
}
}
有了这个设计,就不需要你当前的扩展方法了,因为对于 Projects
您可以使用的查询:
var projects = _ctx.Projects
.Where(p => p.CompanyId == companyId)
.Where(Project.IsVisibleForResearcher(userId));
和Companies
:
var companies = _ctx.Companies
.WhereAny(c => c.Projects, Project.IsVisibleForResearcher(userId));
更新:此解决方案非常有限,因此如果您有不同的用例(尤其是在第二次更新中的 Select
表达式中),您最好求助于一些第 3 方包.例如,这是 LinqKit 解决方案:
// LInqKit requires expressions to be put into variables
var projects = Linq.Expr((Company c) => c.Projects);
var projectFilter = Project.IsVisibleForResearcher(userId);
var companies = db.Companies.AsExpandable()
.Where(c => projects.Invoke(c).Any(p => projectFilter.Invoke(p)))
.Select(c => new CompanyListDto
{
Id = c.Id,
Name = c.Name,
LogoId = c.LogoId,
ProjectCount = projects.Invoke(c).Count(p => projectFilter.Invoke(p))
});
关于c# - Entity Framework 扩展方法 ICollection/IQueryable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40322424/
var page = pagesRepository.GetPages(); var categoryPages = page.ChildCategoryPages; var articlePages
是否可以将 IQueryable 对象转换为 IQueryable,其中 T 是映射实体? (T 将是 POCO 类)。 提前致谢。 最佳答案 就 Cast() 它。假设它是相同类型的可查询。否则你可
我只是想知道为什么会有一个 IQueryable没有通用功能的版本? 最佳答案 The generic IQueryable is the one you use most often in meth
我有一个 IQueryable它是根据一些输入参数(排序和过滤器)创建的。 可以应用这个 IQueryable到 DbSet我有DbContext ? 例如: // create the query
我们正在尝试转换 IQueryable 的实例到 IQueryable , SpecificEntityObject类型仅在运行时已知。 我们已尝试使用下面的代码,该代码无法编译,因为类型或命名空间
最近几天我在互联网上搜索了解决方案,但没有找到我想要的。基本上,这是我的问题: 我有一个需要实现的接口(interface),它有一个返回 IQueryable 的方法(我无权访问该接口(interf
与IEnumerable相同对比IEnumerable .这是疏忽吗?或者当您没有指定类型来实现像 .Count() 这样的扩展时,是否存在问题? , .Where()等不可能? 最佳答案 来自doc
这是 Automapper 专业人员的问题。我已经尝试做查询映射好几天了——但没有成功。似乎 Automapper 不打算按照我想要的方式使用它。但也许我错了。那么问题来了…… 我有这样的类(clas
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭去年。 Improve th
我有一个类Something实现 ISomething .如何从 IQueryable 转换/转换到 IQueryable .当我尝试转换时,我能够编译,但转换的结果始终为 NULL。 背景:我这样做
我了解协方差,并且我知道一般来说在 v4.0 之前它在 C# 中是不可能的。 但是我想知道一个具体案例。有什么方法可以进行转换IQueryable至IQueryable通过以某种方式创建一个包装类,该
如果IQueryable接口(interface)在服务器中执行查询表达式,而不是像 IEnumerable 那样获取所有记录,为什么是IQueryable未被 IEnumerable 取代哪里可以更
这个问题在这里已经有了答案: Why covariance and contravariance do not support value type (4 个答案) 关闭 7 年前。 为什么编译器不
我想做这样的事情 public IQueryable GetPaged(IQueryable query, int startIndex, int pageSize) {
我正在开发一个使用新 Web API 的项目,我注意到有人从 Get 方法返回了一个 IQueryable。 我的理解是 IQueryable 可用于提高性能(延迟执行),但我认为 HTTP 连接另一
我正在重构我的 EF 存储库类以使其可测试,遵循这篇优秀博客文章中的建议: https://blog.iannelson.uk/testing-linq-queries/ 一切都很好,我也能够像在博客
我有一个包含 IQueryable 的通用函数其中每一行都包含一个具有一组属性的类的实例。 我有另一个类 (MyClass),它具有与上面的类 T 相同的一些属性...即相同的名称和数据类型。 我还有
我正在尝试使用 Automapper 将 IQueryable 映射到 IQueryable 以生成 Linq。我正在开发一个带有 Entity Framework 和 oracle 11g 的 We
我有一个对象是: IQueryable 我想将它传递给一个函数,该函数需要: IQueryable Foo 确实实现了 IFoo 为什么不能编译?什么是最好的转换方式来让这项工作发挥作用? 最佳答案
我有一个查询可以获取一些过滤后的数据,但它给了我一些奇怪的结果。使用 VS Code 调试器查看附件图像(var source 是一个 Queryable,类似于 _dbContext.ModelNa
我是一名优秀的程序员,十分优秀!