我正在使用Code First方法学习实体框架。我有两个关系,一对一的关系:
public class Product
{
[Key]
public int ProductID { get; set; }
public string ProductName { get; set; }
//Foreign Key -----> To establish relationship btw two tables.
public int CategoryID { get; set; }
// A product belongs to a ----> Category
public virtual ProductCategory Category { get; set; }
}
public class ProductCategory
{
[Key] //PK
public int CategoryID { get; set; }
public string CategoryName { get; set; }
// A Category ----> has many products (List of Products)
public virtual List<Product> ProductList { get; set; }
}
我的DbContext类:
class ModelDBEntitiesContext2 : DbContext
{
public ModelDBEntitiesContext2()
{
//turns off easy loading for all Entities---> use Eager loading to load related Entities by using "Include"
this.Configuration.LazyLoadingEnabled = false;
}
public DbSet<Product> products { get; set; }
public DbSet<ProductCategory> categories { get; set; }
}
我使用linq方法语法使用INCLUDE(Eager Loading)字来查询所有产品和所有产品及其类别,如下所示:
ModelDBEntitiesContext2 db = new ModelDBEntitiesContext2();
var pppp = db.products.Include(c => c.Category).ToList();
//I bind it to a datagrid view
dataGridView.DataSource = pppp;
对dataGridView的查询结果显示客户的列返回System.Data.Entity.DynamicProxies.ProductCategory
DataGridView Result
我到底做错了什么?为什么即使使用Include也无法检索所有产品的类别。
答案 0 :(得分:3)
通过将子类导航属性标记为虚拟,EF将使用代理包装引用以启用延迟加载&amp;改变跟踪,无论你是否渴望加载。如果删除虚拟声明,它会将引用保留为“类别”,但是您需要始终急切加载该属性,否则它将作为#null返回。但是,在大多数情况下,您不应该这样做,因为使用EF的目的在于更改跟踪。
扩展Peter&amp;罗伯特的建议:
var pppp = db.products.Include(p => p.Category).ToList();
foreach(var p in pppp)
{
if (p.Category != null)
Console.WriteLine(p.Category.CategoryName); // not WriteLine(p.Category)
}
或者将以下内容添加到Category类中:
public override string ToString()
{
return CategoryName;
}
当您将对象传递给WriteLine等函数时,它们希望使用字符串,该代码将针对其他类型调用.ToString()。类上的.ToString()的默认行为是返回类型名称。