0

我有一个名为 serviceEntryFilter 的过滤器,它的属性 System 可能具有例如 EP1、EP2 或 EP1 的值,有时这个过滤器将为空。如果有多个值或单个值,则查询 (IN) 子句运行良好。如果过滤器值为空,那么我会收到以下错误:

无法创建类型为“System.String[]”的常量值。此上下文仅支持原始类型(“例如 Int32、String 和 Guid”)。

[HttpPost]
        public ActionResult List(string ServiceEntryStatus, string ServiceEntryReconciled, string ServiceEntryReliabilityRecord, string ActiveServiceEntry,
                                    int PageNo, ServiceEntryFilter serviceEntryFilter = null)
        {


           string[] systems = null;


        var list = (from se in db.ServiceEntry
                    join r in db.RunLogEntry on se.RunLogEntryID equals r.ID into joinRunLogEntry
                    from r2 in joinRunLogEntry.DefaultIfEmpty()
                    join u in db.User on se.TechnicianID equals u.ID
                    join s in db.System1 on se.SystemID equals s.ID
                    where (
                        ((se.RunLogEntryID == 0 || se.RunLogEntryID != null))
                             && ((serviceEntryFilter.ID.HasValue == false) || (se.ID == serviceEntryFilter.ID.Value && serviceEntryFilter.ID.HasValue == true))
                            && ((serviceEntryFilter.ServiceDateTime.HasValue == false) || (EntityFunctions.TruncateTime(se.ServiceDateTime) == EntityFunctions.TruncateTime(serviceEntryFilter.ServiceDateTime) && serviceEntryFilter.ServiceDateTime.HasValue == true))
                            && ((serviceEntryFilter.RunDate.HasValue == false) || (EntityFunctions.TruncateTime(r2.RunDate) == EntityFunctions.TruncateTime(serviceEntryFilter.RunDate) && serviceEntryFilter.RunDate.HasValue == true))
                            && ((serviceEntryFilter.Technician == null) || (u.FullName.Contains(serviceEntryFilter.Technician.Trim()) && serviceEntryFilter.Technician != null))
                            && (
                                    ((ServiceEntryStatus == "O" && se.ServiceRequestClosed == false) ||
                                      (ServiceEntryStatus == "C" && se.ServiceRequestClosed == true) ||
                                      (ServiceEntryStatus == "A")
                                    )
                               )
                                   && (
                                    ((ServiceEntryReliabilityRecord == null) ||
                                     (ServiceEntryReliabilityRecord == "N" && se.ReliabilityRecord == false) ||
                                      (ServiceEntryReliabilityRecord == "Y" && se.ReliabilityRecord == true) ||
                                      (ServiceEntryReliabilityRecord == "A")
                                    )
                                )
                            && (
                                    ((ServiceEntryReconciled == null) ||
                                     (ServiceEntryReconciled == "N" && se.Reconciled == false) ||
                                      (ServiceEntryReconciled == "Y" && se.Reconciled == true) ||
                                      (ServiceEntryReconciled == "A")
                                    )
                                )
                                         && (
                                    ((ActiveServiceEntry == null) ||
                                     (ActiveServiceEntry == "N" && se.Active == false) ||
                                      (ActiveServiceEntry == "Y" && se.Active == true) ||
                                      (ActiveServiceEntry == "A")
                                    )
                                )

                                    && (
                                  (s.PlatformID == platformID) || (platformID == 0)
                               )
                        && ((serviceEntryFilter.System == null) || ((serviceEntryFilter.System != null) && systems.Contains(s.SystemFullName)))
                       )
                    orderby se.ID descending
                    select new ServiceSearchEntry()
                    {
                        ID = se.ID,
                        ServiceDateTime = se.ServiceDateTime,
                        Technician = u.FullName,
                        System = s.SystemFullName,
                        ReasonForFailure = se.ReasonForFailure,
                        RunDate = (r2 == null ? (DateTime?)null : r2.RunDate)
                    });

        var listData = list.Skip((page - 1) * PageSize).Take(PageSize);

        ServiceEntriesListViewModel viewModel = new ServiceEntriesListViewModel()
        {
            ServiceSearchEntry = listData,
            PagingInfo = new PagingInfo
            {
                CurrentPage = page,
                ItemsPerPage = PageSize,
                TotalItems = list.Count()
            }
        };



}

问题:

当 SystemFilter.System 为 NULL 时,以下子句将引发错误。当用户不为其选择值时,它有时为空。样本值如下:

EP1、EP2 EP1 TP2、TP3、TP4

&& ((serviceEntryFilter.System == null) || ((serviceEntryFilter.System != null) && systems.Contains(s.SystemFullName)))

如果它有一个值,那么我将它放在一个数组中,它的作用就像一个魅力,它就在它为空的时候。

4

2 回答 2

1

这是Linq to Entities的一个已知限制- 请参阅不支持的引用非标量变量部分。

换句话说,这一行:

systems.Contains(s.SystemFullName)

不能用作 EF 查询的一部分。

于 2013-06-28T15:04:45.010 回答
1

问题是 LINQ 语句中的所有内容都将被转换为 SQL。我在这里看到的并没有真正的条件语句说“如果它实际上为空,请不要尝试添加此数组过滤器”。

我会将systems数组初始化为零长度数组,如果filter.Systems不为空则覆盖它,然后按如下方式制作我的 linq 语句:

systems.Contains(s.SystemFullName)

不要在 LINQ 语句中包含该空检查,因为它没有按照您的预期进行。

要构建条件 LINQ 语句,您可能需要查看 PredicateBuilder:http ://www.albahari.com/nutshell/predicatebuilder.aspx

于 2013-06-28T15:23:41.140 回答