实体框架Lazy和Eager加载返回System.Data.Entity.DynamicProxies.PropertyName

时间:2017-07-24 19:27:42

标签: c# entity-framework linq datagridview

我正在使用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也无法检索所有产品的类别。

1 个答案:

答案 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()的默认行为是返回类型名称。