.net 使用 Entity Framework 4.0 和 WCF 4.0 时出现 DataContractSerializer 错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3372895/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 14:34:31  来源:igfitidea点击:

DataContractSerializer Error using Entity Framework 4.0 with WCF 4.0

.netentity-framework

提问by Brandon

I am attempting to retrieve a list of objects from Entity Framework via WCF, but am receiving the following exception:

我试图通过 WCF 从实体框架检索对象列表,但收到以下异常:

There was an error while trying to serialize parameter http://tempuri.org/:GetAllResult. The InnerException message was 'Type 'System.Data.Entity.DynamicProxies.TestObject_240F2B681A782799F3A0C3AFBE4A67A7E86083C3CC4A3939573C5410B408ECCE' with data contract name 'TestObject_240F2B681A782799F3A0C3AFBE4A67A7E86083C3CC4A3939573C5410B408ECCE:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details.

尝试序列化参数http://tempuri.org/:GetAllResult 时出错。该消息的InnerException是“类型‘System.Data.Entity.DynamicProxies.TestObject_240F2B681A782799F3A0C3AFBE4A67A7E86083C3CC4A3939573C5410B408ECCE’数据合同名称‘TestObject_240F2B681A782799F3A0C3AFBE4A67A7E86083C3CC4A3939573C5410B408ECCE:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies’预计不会。考虑使用 DataContractResolver 或将任何静态未知的类型添加到已知类型列表中 - 例如,通过使用 KnownTypeAttribute 属性或将它们添加到传递给 DataContractSerializer 的已知类型列表中。有关更多详细信息,请参阅 InnerException。

I have used WCF in the past, but never with Entity Framework. I have all my entities generated via Entity Framework and are annotated with [DataContract] and [DataMember] attributes. I have no Navigation Properties on any of my entities.

我过去使用过 WCF,但从未使用过实体框架。我的所有实体都是通过实体框架生成的,并用 [DataContract] 和 [DataMember] 属性进行注释。我的任何实体都没有导航属性。

The GetAll() method being called is in an abstract service class:

被调用的 GetAll() 方法位于抽象服务类中:

[ServiceContract]
public interface IService<T>
{
    [OperationContract]
    List<T> GetAll();
}

And I am using the ChannelFactory to call my implementation:

我正在使用 ChannelFactory 来调用我的实现:

Binding binding = new NetTcpBinding();
EndpointAddress endpointAddress = new EndpointAddress("net.tcp://localhost:8081/" + typeof(TestObjectService).Name);
using (ChannelFactory<ITestObjectService> channel = new ChannelFactory<ITestObjectService>(binding, endpointAddress))
{
    ITestObjectService testObjectService = channel.CreateChannel();
    testObjects = testObjectService.GetAll();
    channel.Close();
}

I am hosting it as such:

我是这样主持的:

Type type = typeof(TestObjectService);
ServiceHost host = new ServiceHost(type,
            new Uri("http://localhost:8080/" + type.Name),
            new Uri("net.tcp://localhost:8081/" + type.Name));
host.Open();

When using debugging, it finds the objects from the database, however, it is failing returning the objects.

使用调试时,它从数据库中找到对象,但是返回对象失败。

Any ideas as to where I may be going wrong?

关于我可能哪里出错的任何想法?

回答by Brandon

This was a pain to figure out but it is because EntityFramework creates a 'proxy' of your class. The TestObject class I had was setup correctly, but it was creating a class called: TestObject_240F2B681A782799F3A0C3AFBE4A67A7E86083C3CC4A3939573C5410B408ECCE

这很难弄清楚,但这是因为 EntityFramework 创建了您的类的“代理”。我的 TestObject 类设置正确,但它创建了一个名为的类:TestObject_240F2B681A782799F3A0C3AFBE4A67A7E86083C3CC4A3939573C5410B408ECCE

To make the ChannelFactory + WCF + Entity Framework all work together, you must go into your Context constructor and add the following:

要使 ChannelFactory + WCF + Entity Framework 一起工作,您必须进入 Context 构造函数并添加以下内容:

ContextOptions.ProxyCreationEnabled = false;

I hope this helps someone else.

我希望这对其他人有帮助。

回答by a-h

When using the DbContext API for Code First (EF 4.3) I had to do:

将 DbContext API 用于 Code First (EF 4.3) 时,我必须执行以下操作:

public class MyClass : DbContext
{
    public MyClass()
    {
        base.Configuration.ProxyCreationEnabled = false;
    }
}

回答by georger

For EntityFramework 6.0 I had to change configuration as well:

对于 EntityFramework 6.0,我也必须更改配置:

public class MyContext : DbContext
{
    public MyContext() : base("name=MyContext")
    {
        Configuration.ProxyCreationEnabled = false;
    }
}

回答by Serj Sagan

You have several other options other than adding no proxy to your entire POCO:

除了不向整个 POCO 添加代理之外,您还有其他几种选择:

1) Create a wrapper/DTO. In an API, it is likely that you don't want to expose the whole POCO to your users... so create a wrapper object that only exposes the stuff you want, and this also solves the proxy problem.

1) 创建一个包装器/DTO。在 API 中,您可能不想将整个 POCO 公开给您的用户……因此创建一个仅公开您想要的内容的包装器对象,这也解决了代理问题。

1.5) Pretty much like 1, but instead of creating a wrapper, just return an anonymous type(with LINQ)

1.5) 与 1 非常相似,但不是创建包装器,而是返回一个anonymous type(with LINQ)

2) If you don't need to do it app wide, it may make more sense to do it in the Controllerwhere you need that serialization... or even more localized to a Method, including using, here's a per Controllerimplementation:

2)如果您不需要在应用程序范围内执行此操作,则Controller在需要序列化的地方执行此操作可能更有意义……或者甚至更本地化为 a Method,包括using,这是每个Controller实现:

public class ThingController : ApiController
{
    public ThingController()
    {
        db = new MyContext();
        db.Configuration.ProxyCreationEnabled = false;
    }

    private MyContext db;

    // GET api/Thing
    public IQueryable<Thing> GetThings()
    {
        return db.Things;
    }

    //...

    protected override void Dispose(bool disposing)
    {
        if (disposing)
            db.Dispose();

        base.Dispose(disposing);
    }
}

3) The other thing is if you're needing it just for that db call, the easiest way to do it is to chain AsNoTracking()into your call:

3)另一件事是,如果您只需要该 db 调用,最简单的方法是链接AsNoTracking()到您的调用中:

List<Thing> things;
using (var db = new MyContext())
{
    things = db.Things.AsNoTracking().ToList();
}

回答by Deepak Pathak

You can instead use a DTO and return that. No need to turn off the Proxycreationenabled property.

您可以改为使用 DTO 并返回它。无需关闭 Proxycreationenabled 属性。