实体框架DbContext:Value不能为null,参数名称为source

Nic*_*ams 4 c# entity-framework c#-4.0 entity-framework-5

我已经开始在实体框架中使用CodeFirst方法.

运行我的代码时,我无法在DbContext - ProductsDb中对DbSets执行任何操作

我检查了连接字符串,我认为它是正确的但尝试执行操作会导致错误

参数源不能为null.

这是ProductsDb类

public class ProductsDb : DbContext
{
    public ProductsDb(string connectionString) : base(connectionString)
    {            
    }

    public ProductsDb()
    {            
    }

    public DbSet<AProduct> AProducts;
    public DbSet<BProduct> BProducts;
    public DbSet<CProduct> CProducts;
    public DbSet<DProduct> DProducts;
}
Run Code Online (Sandbox Code Playgroud)

连接字符串在app.config中定义如下:

<?xml version="1.0" encoding="utf-8" ?>
  <configuration>
    <connectionStrings>
    <add name="ProductsDb" providerName="System.Data.SqlClient" 
      connectionString="Data Source=MyPC\DEV;Initial Catalog=Test;User ID=sa;
      Password=pass;" />
    </connectionStrings>
  </configuration>
Run Code Online (Sandbox Code Playgroud)

抛出错误的代码是:

GetAProduct(string id)
{
   AProduct aProduct = null;

   using (ProductsDb productsDb = new ProductsDb())
   {
        aProduct = (from a in productsDb.AProducts
                    where a.Id== id
                    select a).FirstOrDefault();
   }

   return aProduct;
}
Run Code Online (Sandbox Code Playgroud)

所有产品类都是普通的旧C#类.

任何帮助都会非常感激,我开始拉头了.编写Sql查询时从未遇到任何问题.

更新:复制粘贴错误GetAProduct方法已被更改.

Ser*_*kiy 11

您应该为上下文类中的集定义属性而不是字段.所以,而不是字段

public DbSet<AProduct> AProducts;
Run Code Online (Sandbox Code Playgroud)

你应该使用属性

public DbSet<AProduct> AProducts { get; set; }
Run Code Online (Sandbox Code Playgroud)

因为Entity Framework会查找属性.如果你将探索DbContext类的源代码,你会看到,在构造函数中搜索声明的set属性并初始化它们:

private void DiscoverAndInitializeSets()
{
    new DbSetDiscoveryService(this).InitializeSets();
}
Run Code Online (Sandbox Code Playgroud)

此set discover服务仅查找属性:

var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
var properties = 
   from p in this._context.GetType().GetProperties(flags)
   where (p.GetIndexParameters().Length == 0) && 
         (p.DeclaringType != typeof(DbContext))
   select p);

foreach(PropertyInfo info in properties)
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

如果您将声明DbSet<T>类型的简单字段,EF将跳过它的初始化,并且字段将null在创建上下文后具有值.这就是为什么枚举器在null source这里抛出异常的原因:

productsDb.AProducts.Where(a => a.Id== id)
Run Code Online (Sandbox Code Playgroud)