C# CTP4代码第一个EF4功能中查询后导航属性为Null
我只是先开始玩CTP4和代码。我有以下可能的约会网站设置: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 {
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配合使用的要求…不完全正确为什么…但我觉得它会产生