EF,Code First,WCF => 空集合问题

3

我在使用Ef 4.1的Code First实现时遇到了一些问题。

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异常和关闭的连接。
有什么建议吗?
1个回答

6

如果您想要加载Bars,必须使用急切加载。EF不会自动加载相关对象。您必须始终通过急切加载或延迟加载向EF请求相关对象。如果打开代理创建,则在数据序列化过程中(第一次访问集合时),EF将尝试通过延迟加载来加载Bars集合,但是您将因为上下文关闭或序列化数据中的循环(Bar.Foo和Foo.Bars)而收到异常。

要使用急切加载,您必须将Include方法添加到查询中:

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

为了避免循环,您必须在Bar中删除Foo或使用DataContractIsReference=trueDataMember属性标记FooBar
[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;}
}

否则,您将不得不将 Bar 中的 Foo 属性标记为不进行序列化以打破循环:

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

感谢您的回答。您说“EF从不自行加载相关对象”。嗯,这是不可能的,因为在上面的示例中,如果您打开ProxyCreationEnabled,相关对象确实会被加载。我猜这是Code First框架的一个特性。这让我想到,即使您的解决方案可能有效,但它并不是正确的解决方案。 - HaakonL
这不是 Code First 的特性。它被称为延迟加载,而且它不会自动触发。只有当你开发的代码首次访问导航属性时才会触发。在你的情况下,它将由 WCF 服务执行序列化时触发。 - Ladislav Mrnka
Monkeyboy 11,Ladislav 66k。毋庸置疑,Ladislav 是正确的。 - EightyOne Unite

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接