Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird "assembly not referenced" error when trying to call a valid method overload

I'm using method overloading in Assembly A:

public static int GetPersonId(EntityDataContext context, string name)
{
    var id = from ... in context... where ... select ...;
    return id.First(); 
}

public static int GetPersonId(SqlConnection connection, string name)
{
    using (var context = new EntityDataContext(connection, false))
    {
        return GetPersonId(context, name);
    }
}

When I try to call the second overload from Assembly B, VS produces the following compile-time error:

The type 'System.Data.Entity.DbContext' is defined in an assembly that is not referenced. You must add a reference to assembly 'EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=...'.

Assembly B references Assembly A. Entity Framework is referenced only in Assembly A as Assembly B doesn't use it. The call from Assembly B looks like this:

using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();                               
    var id = AssemblyA.GetPersonId(connection, name); // compiler error
    ...
}  

What I don't understand is that the error goes away if I change the method signature in Assembly A to e.g.:

public static int GetPersonId(SqlConnection connection, string name, bool empty)

and change the call to:

var id = AssemblyA.GetPersonId(connection, name, true); // no error

Why is my code not compiling in the first case? It doesn't seem to be related to Entity Framework as the error indicates. I have always thought that C# allows method overloading where method signatures differ only in parameter types. E.g. I can run the following code without problems as expected:

static void DoStuff(int a, int b) { ... }
static void DoStuff(int a, float b) { ... }

DoStuff(10, 5);
DoStuff(10, 5.0f);

So why am I getting the error in my situation despite the apparently legal overloads?

Note that from Assembly B I have no problems calling other methods that internally use EntityDataContext, the only difference is that these methods don't have overloads.


Background

EntityDataContext inherits EF's DbContext:

public partial class EntityDataContext : DbContext
{
        public EntityDataContext() : base("name=EntityDataContext") { }

        public EntityDataContext(DbConnection connection, bool contextOwnsConnection) 
            : base(connection, contextOwnsConnection) { }

        ...
}

I'm using .NET 4.0 with EF 6 code first to an existing database with some custom ctor overloads added.

like image 317
w128 Avatar asked Oct 13 '14 13:10

w128


1 Answers

The C# standard specifies that overload resolution (section 7.5.3) is performed by comparing each matching signature to determine which is a better fit. It doesn't say what happens when a reference is missing, so we must infer that it still needs to compare those unreferenced types.

In your case, the compiler needs a reference to EntityDataContext to be able to compare the two overloads. Your call matches the signature exactly so in theory you shouldn't need this, but the standard doesn't specify any such short-circuit behavior.

like image 56
Cory Nelson Avatar answered Oct 23 '22 04:10

Cory Nelson