这是我第一次使用Entity Framework 4.3.1在C#中创建项目。我很难从锦标赛表中获取所有数据,确切地说是地址。
首先,这是我的Code First代码。当我运行它时,正确创建2个表与正确的关系。我在这些类中定义了更多的列,但是对于这个例子,我只展示了一些。
public class EFDbContext : DbContext
{
public EFDbContext()
: base("ApplicationServices")
{
}
public DbSet<Tournament> tournaments { get; set; }
public DbSet<Address> addresses { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
public class Tournament
{
[ScaffoldColumn(false)]
public int TournamentId { get; set; }
[Required(ErrorMessage="Tournament name is a required field")]
public string Name { get; set; }
[Required(ErrorMessage="Address is a required field")]
public Address Address { get; set; }
}
public class Address
{
[ScaffoldColumn(false)]
public int AddressId { get; set; }
[Required(ErrorMessage="Street name is a required field")]
public string Street { get; set; }
[Required(ErrorMessage="House number is a required field")]
public string HouseNo { get; set; }
}
}
当我插入带有地址的新锦标赛时,如果使用该关系,我会检查数据库,我可以看到它有效。锦标赛的Address_AddressId值指向新插入的地址。但是,当我尝试通过这样做获取信息时:
Tournament tournament = context.tournaments.Find(id);
我调试它,我可以看到锦标赛的所有数据都在锦标赛对象中,地址除外。这被设置为null,我完全不知道为什么。
你们可以帮助我吗?
提前致谢, 巴特
答案 0 :(得分:3)
您需要熟悉一下如何使用Entity Framework加载相关数据。这里有一个介绍:http://blogs.msdn.com/b/adonet/archive/2011/01/31/using-dbcontext-in-ef-feature-ctp5-part-6-loading-related-entities.aspx这些是您需要了解的有效使用Entity Framework的基础知识。
您所看到的行为是预期的。当你刚刚加载父实体Tournament.Address
(在你的例子中带有Tournament
)时,实体框架不会自动加载导航属性(如Find
)。
加载相关数据基本上有三个选项:
渴望加载:
Tournament tournament = context.tournaments
.Include(t => t.Address) // <- "eager loading"
.SingleOrDefault(t => t.TournamentId == id);
锦标赛和地址将在一次往返和数据库查询中加载。
延迟加载:将导航属性标记为virtual
:
public virtual Address Address { get; set; }
当你加载锦标赛时,EF会动态创建一个代理对象(派生自Tournament
),只要你访问其中一个属性就能加载相关实体:
Tournament tournament = context.tournaments.Find(id);
string street = tournament.Address.Street; // second query to DB happens here
明确加载:
Tournament tournament = context.tournaments.Find(id);
context.Entry(tournament).Reference(t => t.Address).Load();
// second query to DB happens here
这类似于延迟加载,因为您还需要对数据库进行两次查询和往返,但是在加载Address
时您将明确控制。显式加载可以选择过滤或排序其他两个选项所没有的相关数据(如果是导航集合)。