我已经阅读了几个关于实体框架生成对象的WCF序列化的问题/文章,但我发现的所有解决方案都涉及开启急切加载,这正是我不想做的事情。
我基本上得到了与The ObjectContext instance has been disposed - Winforms Entity Framework中提到的相同的错误,不同之处在于我正在从Silverlight应用程序中使用我的WCF服务。
我有一个表User_Notifications
,它有一个表User_Info
的外键。 (如果我没有正确使用术语,单个User_Info
可以指向多个User_Notifications
。我正在使用Entity Framework 4,它为这两者创建了一个类。我有一个返回的WCF调用:
return DBEntity.User_Notifications.Where(w => w.UserGUID == UserGuid && w.IsDismissed == false).ToArray();
这给了我所需的所有User_Notifications
,但是我得到一个ObjectContext实例已在客户端处置错误,这看起来像是试图加载相关的User_Info
类。我不想要User_Info
数据,我希望它只是保持null或者其他什么,我不需要它来显示通知。
那么,如何在不需要传递关联对象的情况下传递我的实体对象?
我的老板说这只是“我们不需要数据库中的外键”的另一个原因,我真的不想走这条路。
答案 0 :(得分:0)
对于它的价值,坚持不在DB中使用外键。他们应该在那里,期间。
就你的问题而言...听起来你想要返回一个User_Notifications集合,其中User_Info对象未在初始查询中加载,对吧?默认情况下,对表的查询不应该急于加载关联的对象。
在您的服务功能中,只需:
return (from n in DBEntity.User_Notifications
where n.UserGUID == UserGuid && n.IsDismissed == false
select n).ToArray();
如果您发现在客户端需要User_Info对象,那么只需将上面的内容更改为:
return (from n in DBEntity.User_Notifications.Include("User_Info")
....
答案 1 :(得分:0)
我的建议是不要直接通过WCF公开您的EF实体,而是通过您的服务公开DTO。
这有两个好处,首先,你正在处理真正的POCO(不是延迟加载的代理),它们中没有持久的特定细节。第二个是你只暴露消费者实际需要的东西,这意味着你可以在不强迫客户重新编译的情况下改变底层实现,而且你不必将整个数据模型公开给他们。
在您的示例中,您可以:
// I'm not a fan of the Dto suffix, but it makes this example easier
public class UserNotificationDto
{
// the properties you want to expose through WCF
public Guid UserGuid { get; set; }
public string Message { get; set; }
// ...
}
// your service method
IEnumerable<UserNotificationDto> GetNotifications(Guid userGuid)
{
using (var ctx = new Context())
{
return ctx.User_Notifications
.Where(x => !x.IsDismissed && x.UserGuid == userGuid)
.Select(
x => new UserNotificationDto {
UserGuid = x.UserGuid,
Message = x.Message
}
).ToList();
}
}
您可以使用automapper使EF实体和DTO之间的转换更容易,但这只是一个人为的例子。