实体框架中的可空实体投影

时间:2020-03-06 14:47:33  来源:igfitidea点击:

我有以下SQL Server 2005数据库架构:

CREATE TABLE Messages (
   MessageID int,
   Subject varchar(500),
   Text varchar(max) NULL,
   UserID NULL
)

可以为空的" UserID"列是一个外键,并链接到该表

CREATE TABLE Users (
   UserID int,
   ...
)

现在,我有几个名称为Message,User等的POCO类,可在以下查询中使用:

public IList<Message> GetMessages(...) {
  var q = (from m in dataContext.Messages.Include("User")
           where ...
           select m); // could call ToList(), but...

  return (from m in q
          select new Message {
            ID = m.MessageID,
            User = new User {
              ID = m.User.UserID,
              FirstName = m.User.FirstName,
              ...
            }
          }).ToList();
}

现在注意,我建议使用Include(" Users")的实体框架加载与消息关联的用户(如果有)。另请注意,在第一个LINQ语句之后,我不调用ToList()。这样,仅从投影列表中指定的列(在这种情况下,将从数据库中返回MessageID,UserID,FirstName)。

这是问题所在,一旦Entity Framework遇到带有UserID == NULL的消息,它就会引发异常,原因是它无法转换为Int32,因为DB值为NULL。

如果我将最后两行更改为

return (from m in q
        select new Message {
           ID = m.MessageID,
           User = m.User == null ? null : new User {
              ID = m.User.UserID,
              ...
           }
        }).ToList()

然后抛出运行时NotSupportedException,表明它无法创建恒定的User类型,并且仅支持int,string,guid之类的原语。

除了在第一个语句之后立即实现结果并随后使用内存中的投影之外,还有人知道如何处理它吗?谢谢。

解决方案

我怀疑关系不是一对一的。

由于我们做了.Include(" Users"),因此我们应该能够遍历Message对象中的User属性来获取所需的信息。

我们忘记了包含" Message"类的声明,但是我怀疑该类中的UserID属性未声明为可空类型。如果是这种情况,请将其从" int"更改为" int?"。 (可为null的int)。