Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Internal access for entities in Entity Framework makes simple linq where query crash

I am developing a library which use EF for database access. To avoid expose the entities outside the library, I have set the access of all tables to internal (I have also set to internal the Entity Container Access). The problem is that now, inside the library, when I try to get an entity by its id, the Where query throws an exception, I do not why.

The internal access has been set in the diagram (.edmx file), and in a static class that I am using as a factory inside the library I have something like this:

var id = 1234;
var mec = new MyEntitiesContainer();
var myEntity = mec.MyEntities.Where(e => e.MyEntitiesId == id).FirstOrDefault();

Simple where query to get a concrete entity (row) from the database by its id.

When all entities class access are public, there is no problem, but when I have set them to internal this exception is thrown:

System.ArgumentNullException: Value cannot be null.  Parameter name: source     
    at System.Linq.Queryable.Where[TSource](IQueryable`1 source, Expression`1 predicate)

Any suggestions?

like image 814
RodrigoDominguez Avatar asked Dec 19 '12 10:12

RodrigoDominguez


1 Answers

Update! Actually found a more direct working solution to this problem:

  1. Open the edmx in the designer
  2. Set "Entity Container Access" to Internal
  3. Be sure all Entities have "Access" set to Public
  4. Expand the edmx and edit the entity t4 (NOT the *.Context.tt)
  5. In the t4 search for Accessibility.ForType(entity) and replace it with "Internal" (or "Friend" for VB)
  6. Save/Re-run the T4 and that's it.

After following those steps no part of your EF items should be visible outside the Assembly and everything should "just work".

If you still experience the "Value cannot be null" exception see the "gotcha" at the bottom of this post.




This is already answered here: c# DbSet - Internal object cannot be got

The gist is that if you set an entityset/dbset property as internal it will not be automatically instantiated by EF. But you can manually instantiate it as described in the accepted answer on that page.




Another gotcha to look out for:

There is a bug in VS2012 (version 11.0.60610.01 Update 3 is my current environment) where the designer won't properly set items back to Public in the underlying edmx file even though it reports as though it does.

So even after setting items back to public, re-running the context t4 and rebuilding you'll still receive that exception.

The only workaround I've found is to open the edmx file and edit it manually, setting the internals back to public.

like image 89
TheLostBrain Avatar answered Sep 22 '22 20:09

TheLostBrain