如何从实体框架导航属性创建LINQ表达式?
我有以下代码:如何从实体框架导航属性创建LINQ表达式?,linq,entity-framework,linq-to-entities,lambda,Linq,Entity Framework,Linq To Entities,Lambda,我有以下代码: Expression<Func<Subscription, Service>> service2= subscription => (from relationship in subscription.ChildRelationships select relationship.SecondService).FirstOrDefault(); Expression service2=subscription=>(来自subscription
Expression<Func<Subscription, Service>> service2= subscription => (from relationship in subscription.ChildRelationships
select relationship.SecondService).FirstOrDefault();
Expression service2=subscription=>(来自subscription.ChildRelationships中的关系
选择relationship.SecondService).FirstOrDefault();
它创建了一个表达式,我可以稍后将其用作实体框架查询的一部分。我使用的实际代码有一个where子句,但为了可读性,我省略了它。这很好,我可以在LINQPad中运行它,我正在使用它进行测试
如果我将代码更改为:
Expression<Func<Subscription, IQueryable<Service>>> service2= subscription => (from relationship in subscription.ChildRelationships
select relationship.SecondService);
Expression service2=subscription=>(来自subscription.ChildRelationships中的关系
选择relationship.SecondService);
它不再编译,并出现以下错误:
无法将lambda表达式转换为
委托类型
'System.Func'
因为
块不是隐式的
可转换为代表返回
类型
这似乎是因为作为导航属性的ChildRelationships没有实现IQueryable。它实际上是EntityCollection类型,它实现了IEnumerable,但不适合创建使用EF的表达式
我想我理解为什么第二段代码不起作用,我想知道如何重写它,使它起作用。同样让我困惑的是,为什么第一块代码可以工作。它还使用ChildRelationships导航属性,但在成为与EF一起工作的表达式时没有任何问题
有人能解释一下吗?我想在这种情况下,课堂可能会对你有所帮助:
Expression<Func<Subscription, IQueryable<Service>>> service2 =
CompiledQuery.Compile(
subscription => (
from relationship in subscription.ChildRelationships
select relationship.SecondService
)
);
表达式服务2=
CompiledQuery.Compile(
订阅=>(
来自subscription.ChildRelationships中的关系
选择relationship.SecondService
)
);
问题不在于FirstOrDefault以某种方式使表达式工作;正如你所说,儿童关系本身并不能实现IQueryable。根据您的需要,您可以通过两种不同的方式解决此问题
您可以使用IEnumerable.AsQueryable方法。如果服务已经从上下文加载,这可能是最好的
如果未加载服务,则可以根据需要使用Load或Include方法在适当的时间加载服务,然后使用上述解决方案
如果有对ObjectContext的引用,则可以使用ObjectQuery,它实现IQueryable:
Expression<Func<Subscription, MyEntities, IQueryable<Service>>> service2 =
(subscription, context) => (
from s in context.Subscriptions // here is the IQueryable
where s.Id == subscription.Id
from relationship in s.ChildRelationships
select relationship.SecondService);
表达式服务2=
(订阅、上下文)=>(
来自context.Subscriptions//中的
其中s.Id==subscription.Id
从s.ChildRelationships中的关系
选择relationship.SecondService);
您需要它是可读取的吗?我认为select正在返回一个IEnumerable。LINQ直接在IEnumerables上操作,因此您可以将service2声明为表达式。尝试了该代码,但得到以下结果:源类型为“System.Data.Objects.DataClasses.EntityCollection”的查询表达式中的后续from子句中不允许使用“Data.Service”类型的表达式。调用“SelectMany”时类型推断失败。好的,我正在了解这里的类型。我将重写我的答案。