Bra*_*don 56 .net entity-framework
我试图通过WCF从实体框架中检索对象列表,但我收到以下异常:
尝试序列化参数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.
我过去使用过WCF,但从未使用过Entity Framework.我通过Entity Framework生成了所有实体,并使用[DataContract]和[DataMember]属性进行了注释.我的任何实体都没有导航属性.
被调用的GetAll()方法位于抽象服务类中:
[ServiceContract]
public interface IService<T>
{
[OperationContract]
List<T> GetAll();
}
Run Code Online (Sandbox Code Playgroud)
我正在使用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();
}
Run Code Online (Sandbox Code Playgroud)
我这样托管它:
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();
Run Code Online (Sandbox Code Playgroud)
使用调试时,它会从数据库中找到对象,但是,它无法返回对象.
关于我可能出错的地方的任何想法?
Bra*_*don 90
这很难理解,但这是因为EntityFramework创建了一个类的"代理".我正确设置的TestObject类,但它创建了一个名为的类:TestObject_240F2B681A782799F3A0C3AFBE4A67A7E86083C3CC4A3939573C5410B408ECCE
要使ChannelFactory + WCF + Entity Framework一起工作,您必须进入Context构造函数并添加以下内容:
ContextOptions.ProxyCreationEnabled = false;
Run Code Online (Sandbox Code Playgroud)
我希望这有助于其他人.
a-h*_*a-h 60
当使用DbContext API代码优先(EF 4.3)时,我必须这样做:
public class MyClass : DbContext
{
public MyClass()
{
base.Configuration.ProxyCreationEnabled = false;
}
}
Run Code Online (Sandbox Code Playgroud)
geo*_*ger 20
对于EntityFramework 6.0,我还必须更改配置:
public class MyContext : DbContext
{
public MyContext() : base("name=MyContext")
{
Configuration.ProxyCreationEnabled = false;
}
}
Run Code Online (Sandbox Code Playgroud)
除了不向整个 POCO 添加代理之外,您还有其他几种选择:
1) 创建一个包装器/DTO。在 API 中,您可能不想将整个 POCO 公开给您的用户……因此创建一个仅公开您想要的内容的包装器对象,这也解决了代理问题。
1.5) 与 1 非常相似,但不是创建包装器,而是返回一个anonymous type
(with LINQ
)
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);
}
}
Run Code Online (Sandbox Code Playgroud)
3)另一件事是,如果您只需要该 db 调用,最简单的方法是链接AsNoTracking()
到您的调用中:
List<Thing> things;
using (var db = new MyContext())
{
things = db.Things.AsNoTracking().ToList();
}
Run Code Online (Sandbox Code Playgroud)