program tip

WCF 4.0과 함께 Entity Framework 4.0을 사용하는 DataContractSerializer 오류

radiobox 2020. 12. 28. 08:00
반응형

WCF 4.0과 함께 Entity Framework 4.0을 사용하는 DataContractSerializer 오류


WCF를 통해 Entity Framework에서 개체 목록을 검색하려고하는데 다음 예외가 발생합니다.

http://tempuri.org/:GetAllResult 매개 변수 직렬화를 시도하는 중에 오류가 발생했습니다 . 다음의 InnerException 메시지가 TestObject_240F2B681A782799F3A0C3AFBE4A67A7E86083C3CC4A3939573C5410B408ECCE '데이터 계약 이름' '유형'System.Data.Entity.DynamicProxies.TestObject_240F2B681A782799F3A0C3AFBE4A67A7E86083C3CC4A3939573C5410B408ECCE했다 http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies가 '예상되지 않는다. DataContractResolver 사용을 고려하거나 정적으로 알려지지 않은 모든 유형을 알려진 유형 목록에 추가하십시오 (예 : KnownTypeAttribute 특성을 사용하거나이를 DataContractSerializer에 전달 된 알려진 유형 목록에 추가). ' 자세한 내용은 InnerException을 참조하십시오.

과거에는 WCF를 사용했지만 Entity Framework에서는 사용하지 않았습니다. Entity Framework를 통해 생성 된 모든 엔터티가 있고 [DataContract] 및 [DataMember] 특성으로 주석이 추가되었습니다. 내 엔터티에 탐색 속성이 없습니다.

호출되는 GetAll () 메서드는 추상 서비스 클래스에 있습니다.

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

그리고 내 구현을 호출하기 위해 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();
}

나는 그것을 다음과 같이 호스팅하고 있습니다.

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();

디버깅을 사용할 때 데이터베이스에서 개체를 찾지 만 개체 반환에 실패합니다.

내가 어디로 잘못 가고 있는지에 대한 아이디어가 있습니까?


이것은 알아 내기가 힘들었지 만 EntityFramework가 클래스의 '프록시'를 생성하기 때문입니다. 내가 가지고 있던 TestObject 클래스는 올바르게 설정되었지만 TestObject_240F2B681A782799F3A0C3AFBE4A67A7E86083C3CC4A3939573C5410B408ECCE라는 클래스를 생성했습니다.

ChannelFactory + WCF + Entity Framework가 모두 함께 작동하도록하려면 Context 생성자로 이동하여 다음을 추가해야합니다.

ContextOptions.ProxyCreationEnabled = false;

다른 사람에게 도움이되기를 바랍니다.


Code First (EF 4.3) 용 DbContext API를 사용할 때 다음을 수행해야했습니다.

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

EntityFramework 6.0의 경우 구성도 변경해야했습니다.

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

전체 POCO에 프록시를 추가하지 않는 것 외에 몇 가지 다른 옵션이 있습니다.

1) 래퍼를 만듭니다. API에서 전체 POCO를 사용자에게 노출하고 싶지 않을 가능성이 있으므로 원하는 항목 만 노출하는 래퍼 객체를 생성하면 프록시 문제도 해결됩니다.

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 Controller where you need that serialization... or even more localized to a Method, including using, here's a per Controller implementation:

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:

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

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

ReferenceURL : https://stackoverflow.com/questions/3372895/datacontractserializer-error-using-entity-framework-4-0-with-wcf-4-0

반응형