【问题标题】:Null coalescing operator not working in Entity Framework 6空合并运算符在实体框架 6 中不起作用
【发布时间】:2016-10-18 22:00:46
【问题描述】:

我目前正在将应用程序从 EF5 迁移到 EF6,但在运行此查询的单元测试中遇到了问题:

return (from employeeWorkLocation in Retrieve()
                    where employeeWorkLocation.ClientId == clientId
                     && employeeWorkLocation.EmpUid == empUid
                     && employeeWorkLocation.EffectiveDate <= effectiveDate
                     && (!employeeWorkLocation.EffectiveEndDate.HasValue || employeeWorkLocation.EffectiveEndDate > effectiveDate)
                    join locationEntity in Context.WorkLocationEntities on employeeWorkLocation.WorkLocationUid equals locationEntity.WorkLocationUid into workLocations
                    from workLocation in workLocations.Where(wl => wl.Inactive == GenericYesNo.NO).DefaultIfEmpty()
                    select new EmployeeWorkLocation()
                    {
                        ClientId = employeeWorkLocation.ClientId,
                        EffectiveDate = employeeWorkLocation.EffectiveDate,
                        EffectiveEndDate = employeeWorkLocation.EffectiveEndDate,
                        EmployeeWorkLocationUid = employeeWorkLocation.EmployeeWorkLocationUid,
                        EmpUid = employeeWorkLocation.EmpUid,
                        MetaApplication = employeeWorkLocation.MetaApplication,
                        //MetaDateCreated = employeeWorkLocation.MetaDateCreated ?? DateTimeHelper.NowUnspecified,
                        MetaCreatedBy = employeeWorkLocation.MetaCreatedBy,
                        //MetaDateUpdated = employeeWorkLocation.MetaDateUpdated ?? DateTimeHelper.NowUnspecified,
                        MetaUpdatedBy = employeeWorkLocation.MetaUpdatedBy,
                        WorkLocationUid = employeeWorkLocation.WorkLocationUid,
                        HrLocationUid = workLocation.HRPLocationUid
                    }).OrderByDescending(e => e.EffectiveDate).FirstOrDefault();

由于某种原因,如果我删除上面的 cmets,我会收到此错误:

System.Data.Entity.Core.EntityCommandExecutionException:错误 执行命令定义时发生。见内 细节例外。 ---> System.ArgumentException:参数类型 不匹配

我尝试将这些行更改为长版本(三元运算符),但仍然没有运气。我得到同样的错误:

MetaDateCreated = employeeWorkLocation.MetaDateCreated != null ? employeeWorkLocation.MetaDateCreated.Value : DateTimeHelper.Now 未指定,

employeeWorkLocation.MetaDateCreatedemployeeWorkLocation.MetaDateUpdated 都是可以为空的 Datetime? 类型

DateTimeHelper.NowUnspecifiedDatetime 不可为空的类型。与MetaDateCreatedMetaDateUpdated 相同

有什么想法吗?这在 Entity Framework 5 中运行良好

更新:这是DateTimeHelper.NowUnspecified的定义:

public static DateTime NowUnspecified
{
    get
    {
        return DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Unspecified);
    }
}

如果我按照 cmets 中的建议将 DateTimeHelper.NowUnspecified 替换为 DateTimeHelper.Now,我的测试将通过...

Update2: 使用 LinqPad 隔离问题后,我意识到 Entity Framework 6 正在正确处理查询。问题在于抛出异常的 Effort.EF6 库

谢谢,

【问题讨论】:

  • 什么是DateTimeHelper.NowUnspecified
  • @IvanStoev 它属于DateTime 类型。不可为空。我会把它添加到描述中
  • 改用DateTime.Now 看看是否有帮助。
  • DateTime.Now 有效!!,为什么其他辅助方法不起作用?我把定义放在我的问题中..
  • 一般 EF 不喜欢自定义方法。您可以尝试的另一件事是将其移动到查询之外的变量,例如var defaultDate = DateTimeHelper.NowUnspecified; 并在里面使用该变量。

标签: c# entity-framework-6


【解决方案1】:

问题是 EF 不知道如何将您的属性转换为 sql。如果您确实需要使用该属性(或将来遇到类似情况),您可以通过强制 EF 在该部分逻辑之前执行查询并在本地应用它来实现:

return (from employeeWorkLocation in Retrieve()
                    where employeeWorkLocation.ClientId == clientId
                     && employeeWorkLocation.EmpUid == empUid
                     && employeeWorkLocation.EffectiveDate <= effectiveDate
                     && (!employeeWorkLocation.EffectiveEndDate.HasValue || employeeWorkLocation.EffectiveEndDate > effectiveDate)
                    join locationEntity in Context.WorkLocationEntities on employeeWorkLocation.WorkLocationUid equals locationEntity.WorkLocationUid into workLocations
                    from workLocation in workLocations.Where(wl => wl.Inactive == GenericYesNo.NO).DefaultIfEmpty()
                    select new{employeeWorkLocation, workLocation})
                    .ToArray() //this will cause EF to run the query
                    //Everything below this runs in the .NET code 
                    //rather than on sql server
                    .Select(wl => new EmployeeWorkLocation()
                    {
                        ClientId = wl.employeeWorkLocation.ClientId,
                        EffectiveDate = wl.employeeWorkLocation.EffectiveDate,
                        EffectiveEndDate = wl.employeeWorkLocation.EffectiveEndDate,
                        EmployeeWorkLocationUid = wl.employeeWorkLocation.EmployeeWorkLocationUid,
                        EmpUid = wl.employeeWorkLocation.EmpUid,
                        MetaApplication = wl.employeeWorkLocation.MetaApplication,
                        MetaDateCreated = wl.employeeWorkLocation.MetaDateCreated ?? DateTimeHelper.NowUnspecified,
                        MetaCreatedBy = wl.employeeWorkLocation.MetaCreatedBy,
                        MetaDateUpdated = wl.employeeWorkLocation.MetaDateUpdated ?? DateTimeHelper.NowUnspecified,
                        MetaUpdatedBy = employeeWorkLocation.MetaUpdatedBy,
                        WorkLocationUid = wl.employeeWorkLocation.WorkLocationUid,
                        HrLocationUid = wl.workLocation?.HRPLocationUid
                    }).OrderByDescending(e => e.EffectiveDate).FirstOrDefault();

【讨论】:

  • 您可以将.OrderByDescending(...) 移动到.ToArray() 调用之前。你可以.AsEnumerable() 而不是.ToArray(),它可以防止物化集合。
  • 我认为您可以通过以下方式保存阅读整个查询结果:(from select new {}).OrderBy().FirstOrDefault(),然后对您留下的单个记录进行投影。
猜你喜欢
  • 2015-01-08
  • 2021-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-10
  • 2010-11-05
  • 1970-01-01
相关资源
最近更新 更多