我对这个问题感到不满。我确实在互联网上找到了一些关于它的东西,但不是一个明确的答案。我的问题:
我必须在MVC3 Web应用程序的Model部分中编写类:
ParentClass和ChildClass
在ParentClass上有一个属性为List的类型的子属性
我使用了EF Code First,它在数据库中为我整齐地生成了父表和子表。
现在我需要一个REST服务,它返回一个List或一个ParentClass。
当我从ParentClass中删除属性Children时没有问题。但随着孩子们的到来,我不断收到错误。
错误: "The type System.Data.Entity.DynamicProxies.ParentClass_A0EBE0D1022D01EB84B81873D49DEECC60879FC4152BB115215C3EC16FB8003A was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically."}
一些代码:
类别:
public class ParentClass
{
public int ID { get; set; }
public string Name {get;set;}
public virtual List<ChildrenClass> Children { get; set; }
}
public class ChildrenClass
{
public int ID { get; set; }
public string MyProperty { get; set; }
}
服务:
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class MyService
{
static MyContext db;
public MyService() { db = new MyContext(); }
[WebGet(UriTemplate = "")]
public List<ParentClass> GetParents()
{
var result = db.Parents.ToList();
return result;
}
callinh这项服务时我不会得到结果。我究竟做错了什么?
我不得不在上下文配置中使用DisableProxyCreation:
[OperationContract]
[WebGet(UriTemplate = "")]
public List<ParentClass> GetParents()
{
using (DBContext context = new DBContext())
{
context.Configuration.ProxyCreationEnabled = false;
List<ParentClass> parents = context.Parents
.Include("Children")
.ToList();
return parents;
}
}
这对我来说很好。
我不得不在上下文配置中使用DisableProxyCreation:
[OperationContract]
[WebGet(UriTemplate = "")]
public List<ParentClass> GetParents()
{
using (DBContext context = new DBContext())
{
context.Configuration.ProxyCreationEnabled = false;
List<ParentClass> parents = context.Parents
.Include("Children")
.ToList();
return parents;
}
}
这对我来说很好。
它似乎是为您的POCO序列化代理类,我的第一个建议是使用proxydatacontractresolver: http://msdn.microsoft.com/en-us/library/system.data.objects.proxydatacontractresolver.aspx。
在加载通过网络服务发送的数据时,我还会明确说明明确的内容......即
将Parent类更改为
public class ParentClass
{
public int ID { get; set; }
public string Name {get;set;}
public List<ChildrenClass> Children { get; set; }
}
更改内容以关闭延迟加载:
默认情况下,在Entity Framework 4中禁用延迟加载
并且在返回通过线路发送的数据时明确指定要加载的内容。
[WebGet(UriTemplate = "")]
public List<ParentClass> GetParents()
{
var result = db.Parents.Include("Children").ToList();
return result;
}
看看以下答案: 实体框架代码优先 - 渴望加载不按预期工作? 更高级的包含电话。
另外,根据经验提供的建议,我不会通过网络返回您的数据类,因为它们构成了Web服务的使用者的合同。您最好使用另一组类来映射数据值。
这样,如果数据类发生更改,除非明确要求,否则不必更改Web服务客户端。
如果您希望在Parent或Child类中有1000行,则使用分页很重要,否则您最终会选择N + 1,请参阅: 什么是SELECT N + 1?。
在某些情况下,一个简单的解决方案是使用包装类,以便公开的所有属性都是已知类型。
通常,您不会在控制器类中使用ObjectContext或DbContext,因此在早期层(业务层或服务层)中,您可以从来自DB的对象快速转换为ViewModel样式对象,类似于您'在MVC应用程序中执行,但不是将它们传递给View,而是将它们返回给调用者。
也许你不能在所有情况下使用它,但通常这是一个可行的妥协。