C# CTP4代码第一个EF4功能中查询后导航属性为Null

C# CTP4代码第一个EF4功能中查询后导航属性为Null,c#,entity-framework-4,code-first,C#,Entity Framework 4,Code First,我只是先开始玩CTP4和代码。我有以下可能的约会网站设置: public class User { [Key] public int Id { get; set; } [Required] public string LoginName { get; set; } [Required] public string Firstname { get; set; } [Required] public string Lastname {

我只是先开始玩CTP4和代码。我有以下可能的约会网站设置:

public class User
{
    [Key]
    public int Id { get; set; }
    [Required]
    public string LoginName { get; set; }
    [Required]
    public string Firstname { get; set; }
    [Required]
    public string Lastname { get; set; }

    public string Street { get; set; }
    [Required]
    public string Zip { get; set; }
    [Required]
    public string City { get; set; }
    [Required]
    public bool Gender { get; set; }
    [Required]
    public int SoughtGender { get; set; }
    [Required]
    public string Password { get; set; }
    [Required]
    public double Latitude { get; set; }
    [Required]
    public double Longitude { get; set; }
}

 public class Vote
{
    [Key]
    public int ID { get; set; }
    [Required]
    public User Voter { get; set; }
    [Required]
    public User TargetUser { get; set; }
    [Required]
    public int Decision { get; set; }
    [Required]
    public DateTime Timestamp { get; set; }
}

 public class MySQLContext : DbContext
{
    public MySQLContext (string constring)
        : base(constring)
    { }

    public DbSet<User> Users { get; set; }
    public DbSet<Vote> Votes { get; set; }

    protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Vote>().HasRequired(b => b.Voter).WithMany();
        modelBuilder.Entity<Vote>().HasRequired(b => b.TargetUser).WithMany();
        base.OnModelCreating(modelBuilder);

    }
}
公共类用户
{
[关键]
公共int Id{get;set;}
[必需]
公共字符串登录名{get;set;}
[必需]
公共字符串名{get;set;}
[必需]
公共字符串Lastname{get;set;}
公共字符串Street{get;set;}
[必需]
公共字符串Zip{get;set;}
[必需]
公共字符串City{get;set;}
[必需]
公共布尔性别{get;set;}
[必需]
public int SoughtGender{get;set;}
[必需]
公共字符串密码{get;set;}
[必需]
公共双纬度{get;set;}
[必需]
公共双经度{get;set;}
}
公投
{
[关键]
公共int ID{get;set;}
[必需]
公共用户投票者{get;set;}
[必需]
公共用户TargetUser{get;set;}
[必需]
公共int决策{get;set;}
[必需]
公共日期时间时间戳{get;set;}
}
公共类MySQLContext:DbContext
{
公共MySQLContext(字符串构造)
:基础(构造)
{ }
公共数据库集用户{get;set;}
公共数据库集投票{get;set;}
模型创建时受保护的覆盖无效(System.Data.Entity.ModelConfiguration.ModelBuilder ModelBuilder)
{
modelBuilder.Entity().HasRequired(b=>b.Voter).WithMany();
modelBuilder.Entity().HasRequired(b=>b.TargetUser).WithMany();
基于模型创建(modelBuilder);
}
}
现在,框架很好地使用所有正确的键创建了数据库。现在,我插入了一些虚拟数据并启动了以下查询:

public override IEnumerable<Domain.Vote> FindVotes(Domain.User user)
    {
        var query = from v in context.Votes where v.Voter.Id == user.Id select v;
        return from v in query.AsEnumerable() select v;
    }
公共覆盖IEnumerable FindVotes(Domain.User)
{
var query=来自上下文中的v.vower,其中v.Voter.Id==user.Id选择v;
从查询中的v返回。AsEnumerable()选择v;
}

查询确实返回正确的投票实体,但投票对象的两个用户属性为Null。框架不应该用投票表中引用的用户的外键填充这些属性吗?

将您的类更改为

public class Vote {
    [Key]
    public int ID { get; set; }
    [Required]
    public virtual User Voter { get; set; }
    [Required]
    public virtual User TargetUser { get; set; }
    [Required]
    public int Decision { get; set; }
    [Required]
    public DateTime Timestamp { get; set; }
}

请注意,我已将virtual添加到投票者和目标用户属性中,您应该可以开始了。

将您的类更改为以下内容

public class Vote {
    [Key]
    public int ID { get; set; }
    [Required]
    public virtual User Voter { get; set; }
    [Required]
    public virtual User TargetUser { get; set; }
    [Required]
    public int Decision { get; set; }
    [Required]
    public DateTime Timestamp { get; set; }
}

请注意,我已经在投票者和目标用户属性中添加了virtual,您应该可以开始了。

让我给您介绍一下EF的背景知识,以便您了解它是如何工作的。从第1天开始的EF仅支持如下所示的显式加载

Customer.Orders.Load();
嗯,社区不欢迎反馈,开发人员希望延迟加载。为了支持延迟加载,EF团队说您必须将导航属性标记为虚拟。因此,在运行时,Ef将创建一个从实体派生的代理对象,并覆盖虚拟属性。下面是此类代码的示例

public class Customer
{
   public string Name{get;set;}
   public virtual ICollection<Order> Orders{get;set;}
}
公共类客户
{
公共字符串名称{get;set;}
公共虚拟ICollection订单{get;set;}
}
在运行时,有一个代理实现了EntityWithChangeTracker,集合的具体类型是entitycollection,它从版本1开始就存在

public class CustomerProxy:Customer,IEntityWithChangeTracker
{
private ICollection<Order> orders;
   public override ICollection<Order> Orders
   {
        if(orders == null)
       {
           orders = new EntityCollection<Order>();
           orders.Load();
       }
       return orders;
   }
}
公共类CustomerProxy:Customer,带ChangeTracker的客户端
{
私人收集令;
公共覆盖ICollection命令
{
if(orders==null)
{
订单=新的EntityCollection();
orders.Load();
}
退货订单;
}
}

让我向您介绍一下EF的背景知识,以便您了解其工作原理。从第1天开始的EF仅支持如下所示的显式加载

Customer.Orders.Load();
嗯,社区不欢迎反馈,开发人员希望延迟加载。为了支持延迟加载,EF团队说您必须将导航属性标记为虚拟。因此,在运行时,Ef将创建一个从实体派生的代理对象,并覆盖虚拟属性。下面是此类代码的示例

public class Customer
{
   public string Name{get;set;}
   public virtual ICollection<Order> Orders{get;set;}
}
公共类客户
{
公共字符串名称{get;set;}
公共虚拟ICollection订单{get;set;}
}
在运行时,有一个代理实现了EntityWithChangeTracker,集合的具体类型是entitycollection,它从版本1开始就存在

public class CustomerProxy:Customer,IEntityWithChangeTracker
{
private ICollection<Order> orders;
   public override ICollection<Order> Orders
   {
        if(orders == null)
       {
           orders = new EntityCollection<Order>();
           orders.Load();
       }
       return orders;
   }
}
公共类CustomerProxy:Customer,带ChangeTracker的客户端
{
私人收集令;
公共覆盖ICollection命令
{
if(orders==null)
{
订单=新的EntityCollection();
orders.Load();
}
退货订单;
}
}

CTP4??你现在真的应该使用RTM版本。实际上它是EF功能包的最新CTP。代码优先仅在即将推出的EF4.CTP4功能包中可用??你现在真的应该使用RTM版本。实际上它是EF功能包的最新CTP。代码优先仅在即将推出的EF4功能包中提供。非常有用,谢谢。这背后的原因是什么?这是为了处理延迟加载。当一个属性被标记为虚拟时,框架类生成器将创建一个派生的代理类,该类将覆盖该属性以进行延迟加载。尽管考虑了它之后,我不完全确定它如何与代码优先的方法配合使用…我必须查找一些内容:)只是解释了POCOs与EF配合使用的要求…不完全正确为什么…但我的印象是它在模型实例化上生成代理类。非常有魅力,谢谢。这背后的原因是什么?这是为了处理延迟加载。当一个属性被标记为虚拟时,框架类生成器将创建一个派生的代理类,该类将覆盖该属性以进行延迟加载。尽管考虑了它之后,我不完全确定它如何与代码优先的方法配合使用…我必须查找一些内容:)只是解释了POCOs与EF配合使用的要求…不完全正确为什么…但我觉得它会产生