具有 EF Code First 的 WebApi 在具有父子关系时会生成错误

发布于 2024-12-16 18:26:19 字数 1313 浏览 3 评论 0原文

我为这个问题伤透了脑筋。我确实在互联网上找到了一些相关内容,但没有明确的答案。我的问题:

我必须在 MVC3 Web 应用程序的模型部分中进行类: 父类和子类 在 ParentClass 上有一个 List 类型的属性 Children

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

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

当我从 ParentClass 中删除 Children 属性时,没有问题。但是对于那里的财产儿童,我不断收到错误。

错误:“不是预期类型 System.Data.Entity.DynamicProxies.ParentClass_A0EBE0D1022D01EB84B81873D49DEECC60879FC4152BB115215C3EC16FB8003A。使用 XmlInclude 或 SoapInclude 属性指定静态未知的类型。”}

一些代码:

类:

     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;

    }

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

I am breaking my head over this issue. I did find something on the internet about it, but not a clear answer. My problem:

I have to classes in Model section of an MVC3 web app:
ParentClass and ChildClass
On ParentClass there is a property Children of type List

I used EF Code First, which neatly generates a parent table and a child table for me in the database.

Now I need a REST service that gives back a List or a single ParentClass.

When I remove the property Children from the ParentClass there is no problem. But with the propoerty Children there I keep getting an error.

Error: "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."}

Some code:

Classes:

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

Service:

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

    }

I will not get the result when callinh this service. What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

陪我终i 2024-12-23 18:26:19

我必须在上下文配置中禁用ProxyCreation:

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

这对我来说效果很好。

I had to DisableProxyCreation in the context configuration:

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

This worked out for me fine.

空袭的梦i 2024-12-23 18:26:19

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

另外,我会努力在加载通过网络服务发送的数据时明确说明一些事情......即

更改父类以

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 - 预加载未按预期工作? 用于更高级的 Include 调用。

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

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

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

It seems to be serialising the proxy classes for your POCOs, my first recommendation would be to use the proxydatacontractresolver: http://msdn.microsoft.com/en-us/library/system.data.objects.proxydatacontractresolver.aspx.

Also I would work on having things spelt out explicitly when loading data for sending over web service ... i.e.

Change Parent class to

public class ParentClass
{
    public int ID { get; set; }
    public string Name {get;set;}
    public List<ChildrenClass> Children { get; set; }

}

Alter your content to turn off lazy loading:
Disable lazy loading by default in Entity Framework 4

And explicitly specify what you want to load when returning data being sent over the wire.

[WebGet(UriTemplate = "")]
public List<ParentClass> GetParents()
{
    var result = db.Parents.Include("Children").ToList();
    return result;

}

Have a look at the following answer: Entity Framework Code First - Eager Loading not working as expected? for more advanced Include calls.

Also a piece of advice from experience, I wouldn't return your data classes over the wire as they form a contract for the consumer of your web service. You are best to have another set of classes that you map your data values into.

That way if your data classes change, you don't have to change the web service client unless explicitly required.

And using paging is important if you are expecting 1000's of rows in the Parent or Child classes otherwise you end up with N+1 select, see : What is SELECT N+1?.

找个人就嫁了吧 2024-12-23 18:26:19

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

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

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

In some situations a simple solution is to use a wrapper class so that all the properties exposed are known types.

Usually you won't be using an ObjectContext or a DbContext in your controller classes anyway so in an earlier layer (Business or Service layer) you can do a quick translation from the objects coming from the DB into ViewModel style objects, similar to what you'd do in an MVC app, but instead of passing them on to a View you return them to the caller.

Maybe you can't use it in all cases, but often it's a workable compromise.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文