【发布时间】:2010-09-13 12:14:56
【问题描述】:
我有以下 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 告诉它不能创建一个常量用户类型,并且只支持像 int、string、guid 这样的原语。
除了在第一条语句之后立即实现结果并在之后使用内存中投影之外,任何人都知道如何处理它?谢谢。
【问题讨论】:
-
您要投射到的消息类型是否与 m 的类型不同?你为什么要投射?
-
为什么要构造新的 Message 和 User 对象,而不是仅仅使用从 q 中返回的那些?我认为你没有完全正确地使用框架。
-
@DavidB:Message是POCO,m是Entity类。 @Orion Adrian:嗯,我希望以后能缓存查询结果。对于实体对象,您需要手动 Detach() 它们 - 包括所有依赖对象,例如用户在这种情况下,太麻烦了(LINQ2SQL 也有同样的问题)。
标签: .net linq entity-framework