5

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

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

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

值不能为空,参数来源。

这是 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;
}

连接字符串在 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>

引发错误的代码是:

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;
}

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

任何帮助将不胜感激,我开始拔头发了。编写 Sql 查询时永远不会有任何问题。

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

4

3 回答 3

14

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

public DbSet<AProduct> AProducts;

你应该使用属性

public DbSet<AProduct> AProducts { get; set; }

因为实体框架寻找属性。如果您将探索DbContext类的来源,您将看到,在构造函数中搜索声明的集合属性并初始化它们:

private void DiscoverAndInitializeSets()
{
    new DbSetDiscoveryService(this).InitializeSets();
}

此设置发现服务仅查找属性:

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)
{
    // ...
}

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

productsDb.AProducts.Where(a => a.Id== id)
于 2013-07-02T15:23:35.547 回答
3

尽管原因不同,但我收到了相同的错误消息:我制作了 DbContext 使用的所有 POCO(及其属性),internal而不是public. 正如 Sergey Berezovskiy 在他的回答中所证明的那样,EF 要求所有类成员都是公共属性才能初始化它们。更改它们以立即public修复错误。

于 2014-01-31T10:02:44.080 回答
1

对于未来的读者:

我有这个问题试图制作一个“只读”DbContext。(这个特定的项目都是关于“报告”的)。并且只想公开 IQueryable(不是 DbSet)。

我的原始(导致此问题)代码如下所示:

    public IQueryable<OrganizationEntity> Organizations { get; set; }

    public IQueryable<DepartmentEntity> Departments { get; set; }

我修改后的代码看起来像这样。

    internal DbSet<OrganizationEntity> InternalOrganizations { get; set; }

    internal DbSet<DepartmentEntity> InternalDepartments { get; set; }

    public IQueryable<OrganizationEntity> Organizations => this.InternalOrganizations.AsNoTracking();

    public IQueryable<DepartmentEntity> Departments => this.InternalApplicationDetails.AsNoTracking();

现在正在工作。

于 2021-03-18T12:57:17.387 回答