Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从实体框架导航属性创建LINQ表达式?_Linq_Entity Framework_Linq To Entities_Lambda - Fatal编程技术网

如何从实体框架导航属性创建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”时类型推断失败。好的,我正在了解这里的类型。我将重写我的答案。