11

我正在为这个问题头疼。我确实在互联网上找到了一些关于它的东西,但没有一个明确的答案。我的问题:

我必须在 MVC3 Web 应用程序的模型部分上课:ParentClass 和 ChildClass 在 ParentClass 上有一个 List 类型的属性 Children

我使用了 EF Code First,它在数据库中巧妙地为我生成了一个父表和一个子表。

现在我需要一个返回列表或单个父类的 REST 服务。

当我从 ParentClass 中删除属性 Children 时,没有问题。但是对于那里的propoerty 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;

    }

调用此服务时我不会得到结果。我究竟做错了什么?

4

3 回答 3

12

我必须在上下文配置中禁用代理创建:

[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; 
      }
}

这对我来说很好。

于 2011-11-18T16:34:34.883 回答
0

它似乎正在为您的 POCO 序列化代理类,我的第一个建议是使用 proxydatacontractresolver:http: //msdn.microsoft.com/en-us/library/system.data.objects.proxydatacontractresolver.aspx

此外,我会努力在加载数据以通过 Web 服务发送时明确说明内容......即

将父类更改为

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;

}

看看以下答案:Entity Framework Code First - Eager Loading not working as expected? 更高级的包括调用。

同样来自经验的一条建议是,我不会通过网络返回您的数据类,因为它们为您的 Web 服务的消费者形成了合同。您最好拥有另一组将数据值映射到其中的类。

这样,如果您的数据类发生更改,除非明确要求,否则您不必更改 Web 服务客户端。

如果您希望在 Parent 或 Child 类中有 1000 行,则使用分页很重要,否则您最终会得到 N+1 选择,请参阅:什么是 SELECT N+1?.

于 2011-11-18T01:10:46.603 回答
0

在某些情况下,一个简单的解决方案是使用包装类,以便所有暴露的属性都是已知类型。

通常,无论如何您都不会在控制器类中使用 ObjectContext 或 DbContext,因此在较早的层(业务或服务层)中,您可以将来自 DB 的对象快速转换为 ViewModel 样式对象,类似于您的'会在 MVC 应用程序中执行,但不是将它们传递给 View,而是将它们返回给调用者。

也许您不能在所有情况下都使用它,但通常这是一个可行的折衷方案。

于 2012-05-11T17:58:19.903 回答