2011-05-03 58 views
3

我在Ef 4.1代码优先实现时遇到了一些问题。EF,代码优先,WCF =>空收集问题

public class Foo() 
{ 
    public Foo() 
    { 
     Id = Guid.NewGuid(); 
     Bars = new Collection<Bar>(); 
    } 

    public Guid Id { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection Bars { get; set; } 
} 

public class Bar() 
{ 
    public Bar() 
    { 
     Id = Guid.NewGuid(); 
    } 

    public Guid Id { get; set; } 
    public string Name { get; set; } 
    public virtual Foo Foo { get; set;} 
} 

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

    public DbSet<Foo> Foos { get; set; } 
    public DbSet<Bar> Bars { get; set; } 
} 

当我把wcf服务放在上面时,它只返回一个空的Bars集合。如果我打开ProxyCreationEnabled,集合将被填充,但由于EF代理创建,我将获得wcf异常和关闭连接。

有什么建议吗?

回答

6

如果您想要加载Bars,则必须使用预先加载。 EF本身不会加载相关的对象。您必须始终通过加载或延迟加载来向EF询问相关对象。如果打开代理创建,EF将尝试在数据序列化期间通过延迟加载来加载Bars集合(第一次访问集合),但由于封闭上下文或因序列化数据中的循环而导致异常(Bar.FooFoo.Bars创建循环)。

要使用预先加载,你必须添加Include方法来查询:

var data = context.Foos.Include(f => f.Bars).ToList(); 

为了避免循环您必须删除FooBar或标记Foo和酒吧DataContractIsReference=trueDataMember属性:

[DataContract(IsReference=true)] 
public class Foo() 
{ 
    public Foo() 
    { 
     Id = Guid.NewGuid(); 
     Bars = new Collection<Bar>(); 
    } 

    [DataMember] 
    public Guid Id { get; set; } 
    [DataMember] 
    public string Name { get; set; } 
    [DataMember] 
    public virtual ICollection Bars { get; set; } 
} 

[DataContract(IsReference=true)] 
public class Bar() 
{ 
    public Bar() 
    { 
     Id = Guid.NewGuid(); 
    } 

    [DataMember] 
    public Guid Id { get; set; } 
    [DataMember] 
    public string Name { get; set; } 
    [DataMember] 
    public virtual Foo Foo { get; set;} 
} 

或者您将必须标记Foo财产Bar作为未序列化以打破一个周期:

public class Bar() 
{ 
    public Bar() 
    { 
     Id = Guid.NewGuid(); 
    } 

    public Guid Id { get; set; } 
    public string Name { get; set; } 
    [IgnoreDataMember] 
    public virtual Foo Foo { get; set;} 
} 
+0

感谢您的回答。你说“EF从不加载相关的对象”。那么这不可能是真的,就像在上面的例子中,如果你打开ProxyCreationEnabled,相关的对象确实被加载了。我想这是Code First框架的一个特性。这使我认为,即使您的解决方案可能有效,但这不是正确的解决方案。 – HaakonL 2011-05-03 10:20:32

+0

首先不是Code的特征。它被称为延迟加载,并且它本身不会触发。一旦导航属性第一次被您开发的代码访问,它就会触发。在你的情况下,它将由WCF服务完成序列化。 – 2011-05-03 20:43:30

+0

Monkeyboy 11,Ladislav 66k。不用说拉迪斯拉夫是相当正确的。 – Stimul8d 2011-09-11 13:17:00