C# 实体框架 DbContext:值不能为空,参数名称来源
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17429300/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Entity Framework DbContext: Value cannot be null, parameter name source
提问by Nick Williams
I've started out using the CodeFirst approach in the entity framework.
我已经开始在实体框架中使用 CodeFirst 方法。
When running my code I am unable to perform any operation on the DbSets within the DbContext - ProductsDb
运行我的代码时,我无法对 DbContext - ProductsDb 中的 DbSet 执行任何操作
I have checked the connection string and I think it is correct but attempting to perform operation results in the error
我检查了连接字符串,我认为它是正确的,但尝试执行操作导致错误
Value cannot be null, parameter source.
值不能为空,参数来源。
Here is the ProductsDb class
这是 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;
}
The connection string is defined in the app.config as follows:
连接字符串在 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>
The code that throws the error is:
抛出错误的代码是:
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;
}
All of the product classes are plain old C# classes.
所有产品类都是普通的旧 C# 类。
Any help would be really appreciated, I'm starting to pull my hair out. Never have any problems when writing Sql queries.
任何帮助将不胜感激,我开始拉我的头发。编写 Sql 查询时永远不会有任何问题。
UPDATE: Copy Paste error the GetAProduct method has been altered.
更新:复制粘贴错误 GetAProduct 方法已被更改。
采纳答案by Sergey Berezovskiy
You should define properties instead of fields for sets in your context class. So, instead of fields
您应该为上下文类中的集合定义属性而不是字段。所以,而不是字段
public DbSet<AProduct> AProducts;
You should use properties
你应该使用属性
public DbSet<AProduct> AProducts { get; set; }
Because Entity Framework looks for properties. If you will explore sources of DbContextclass, you will see, that in constructor in searches for declared set properties and initializes them:
因为实体框架会查找属性。如果您将探索DbContext类的来源,您将看到,在构造函数中搜索声明的集合属性并初始化它们:
private void DiscoverAndInitializeSets()
{
new DbSetDiscoveryService(this).InitializeSets();
}
This set discover service looks only for properties:
此集合发现服务仅查找属性:
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)
{
// ...
}
If you will declare simple field of DbSet<T>type, EF will skip it's initialization, and field will have value nullafter context is created. Thats why where enumerator was throwing null sourceexception here:
如果您将声明DbSet<T>类型为simple 的字段,EF 将跳过它的初始化,并且null在创建上下文后字段将具有值。这就是为什么枚举器在null source这里抛出异常的原因:
productsDb.AProducts.Where(a => a.Id== id)
回答by GrandMasterFlush
I had the same error message though the cause was different:
I'd made all of the POCOs (and their properties) that were being used by the DbContext internalinstead of public. As Sergey Berezovskiy has demonstrated in his answer, EF requires all class members to be public properties to initalise them. Changing them to publicfixed the error straight away.
尽管原因不同,但我收到了相同的错误消息:我创建了 DbContext 使用的所有 POCO(及其属性),internal而不是public. 正如 Sergey Berezovskiy 在他的回答中所证明的那样,EF 要求所有类成员都是公共属性来初始化它们。更改它们以立即public修复错误。

