7

I've started out using the CodeFirst approach in the entity framework.

When running my code I am unable to perform any operation on the DbSets within the DbContext - ProductsDb

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

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:

<?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.

Any help would be really appreciated, I'm starting to pull my hair out. Never have any problems when writing Sql queries.

UPDATE: Copy Paste error the GetAProduct method has been altered.

4
  • 2
    productsDb, where is come from ? Commented Jul 2, 2013 at 15:15
  • post the code where you are initializing productsDb Commented Jul 2, 2013 at 15:16
  • Going into base -> database -> connection -> connectionstring. The connection string is the same as in the app.config except that it has added 'Application Name=EntityFrameworkMUE' Commented Jul 2, 2013 at 15:25
  • However productDb -> base -> databse -> connection -> serverversion has thrown an error InvalidOperationException Commented Jul 2, 2013 at 15:30

3 Answers 3

16

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 DbContext class, you will see, that in constructor in searches for declared set properties and initializes them:

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 null after context is created. Thats why where enumerator was throwing null source exception here:

productsDb.AProducts.Where(a => a.Id== id)
Sign up to request clarification or add additional context in comments.

2 Comments

Yes thats it. Hate myself quite a bit right now. When have public fields ever been okay????
@PetePetersen I've added code which shows why simple fields will not be initialized
3

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 internal instead 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 public fixed the error straight away.

Comments

1

For future readers:

I have this issue trying to make a "read only" DbContext. (This specific project is all about "reports"). and wanting to expose only IQueryable (not DbSet).

My original (causing this issue) code looked like this:

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

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

My altered code looked like this.

    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();

This is now working.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.