Npgsql - EF6:导航属性子查询上的嵌套FirstOrDefault()抛出"未实现"例外

时间:2014-06-24 15:06:38

标签: entity-framework npgsql entity-framework-6.1

结构是基本的。我有一个“App”父母,有很多“PositionData”孩子。 我想在单个查询中检索“App”的一些基本数据以及该App的Last“PositionData”。

查询

            var data = context.Apps.Where(a => a.Id == appId).
            Select(c => new {
                DeviceInfo=c.Device,
                LastPosition=c.PositionData.OrderByDescending(p=>p.DateCreated).FirstOrDefault() 
            }).SingleOrDefault();

执行以下命令会抛出“System.NotImplementedException”

为了确保仅在子查询的情况下抛出异常,我将其分解为2个查询,并且它完全正常。

            var tempObj = context.Apps.Where(a => a.Id == appId).SingleOrDefault();
            var data=new {
                DeviceInfo=tempObj.Device,
                LastPosition=tempObj.PositionData.OrderByDescending(p=>p.DateCreated)).FirstOrDefault() 
            };

我一直在寻找很多天,也访问过pg代工厂论坛但还没有解决方案。

2 个答案:

答案 0 :(得分:1)

首先我要说,我真的没有postgresql专家。这个问题肯定是一个bug或至少是npgsql提供程序的功能限制。使用Sql Servier提供程序,此语句按预期工作,但它会创建一个非常丑陋且缓慢的TSql语句。

 var data = context.Apps.Where(a => a.Id == appId).
            Select(c => new {
                DeviceInfo=c.Device,
                LastPosition=c.PositionData.OrderByDescending(p=>p.DateCreated).FirstOrDefault() 
            }).SingleOrDefault();

以下陈述显然比你的大得多,但不管你是否相信Store语句更小,更优化。只要您确保PositionData表中的AppId和DateCreated组合是唯一的,结果应该是相同的。

var data = from a in context.Apps
           join pd in context.PositionData.GroupBy(p => p.AppId)
               .Select(p => new { AppId = p.Key, Date = p.Max(x => x.DateCreated) })
               on a.Id equals pd.AppId into pdgrp
           from lpd in pdgrp.DefaultIfEmpty()
           join p in context.PositionData on lpd equals new { AppId = p.AppId, Date = p.DateCreated } into pgrp
           from lp in pgrp.DefaultIfEmpty()
           where a.Id == appId
           select new {
               DeviceInfo = a.Device,
               LastPosition = lp
           };

也许这句话也会转换为Postresql

更新:一些绩效指标。

我已经使用非常快的ssds在本地SQL 2012上进行了测试。对于第一个版本,SQL Server提供程序为第二个LEFT OUTER JOINS创建一个OUTER APPLY语句。 TestData是15 000个应用程序和150 000个PositionData条目。

                 join                      outer apply  
                 reads     duration        reads    duration
all rows          1528          519       444434         912
single row          68            0           35           0

在(AppId ASC,DateCreated DESC)

上添加所需的唯一索引后
all rows           884          220        49875         180
single row          28            0           15           0

答案 1 :(得分:0)

我已在Npgsql Git Hub存储库中打开了该问题。并且看起来这个错误确实是由未实现的Npgsql功能引起的。

他们现在已经实现了该功能并将其合并到主分支。 下载Npgsql和NpgsqlEntityFramework .dll版本> = 2.2将解决此问题。 虽然这个修复程序使用" Lateral"在PostgreSQL v9.3中引入了sql关键字,因此也需要Postgresql版本。