Azure-functions-host: Runtime Exception on Azure Functions with Entity Framework

Created on 19 Nov 2016  路  12Comments  路  Source: Azure/azure-functions-host

Hi, Team.

I've got an issue with running Azure Functions that references to EntityFramework. Here's my SO Question:

http://stackoverflow.com/questions/40671391/azure-functions-with-entity-framework

I referenced an external assembly that are working perfectly fine on my existing application. This is actual implementation of EntityFramework for my database. When you have a look at the SO question above, I provided the complete code, project.json, and exception log details. Of course I copied the external assembly into the bin directory.

Can anyone have a look, please?

improvement

Most helpful comment

@govindsyadv - thanks, that works! So I assumed that by adding the Entity Framework package to the nuget file in my Functions project it would be enough for my satellite assembly to pick it up. But it isn't, I need to copy the EF dll and all the other dll's my satellite needs for operation. So I just greated a gulp file to copy all of them into the bin folder for my function.

Hopefully references will be something coming soon in the tooling.

All 12 comments

Hi, again.

I finally got the root cause. I put a wrong connection string! That caused my error. However, the question still remains. Even though I used an invalid connection string, the error message still shows:

2016-11-19T00:37:51.547 Exception while executing function: Functions.ManualTriggerCSharp2. mscorlib: Exception has been thrown by the target of an invocation. ManualTriggerCSharp2: Could not load file or assembly 'EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' or one of its dependencies. The system cannot find the file specified.

Which doesn't make sense to me. Can we have more specific exception message here?

Hey Justin,
I've commented on the SO question. I'm glad this is working for you. The assembly load error is indeed strange for that error, I'll investigate to see why that was happening in this scenario.

@fabiocav - Will try to create a repro so we can play with exception message

I think there's something else going on here than just Justin's bad connection string. I have a SO post here but I'll reiterate the repro steps.

  1. Create a new Class Library (.net 4.6) in VS 2015.
  2. Pull in EF 6.1.3 from Nuget.
  3. Add this class:
namespace MyLibrary
{
    public class MyContext : System.Data.Entity.DbContext
    {
    }
}
  1. Compile your DLL
  2. Create a new Functions App via the Portal
  3. Copy the DLL to wwwroot/bin
  4. Create Project.json and pull in EF 6.1.3 from Nuget
  5. Set your Run.csx file to look like so:
#r "../bin/MyLibrary.dll"

using System;

public static void Run(TimerInfo myTimer, TraceWriter log)
{
    log.Info("My code: Started");    
    log.Info(typeof(MyLibrary.MyContext).ToString());    
}
  1. Observe that the code compiles correctly.
  2. Run the code and observe the following runtime error:

2017-02-27T06:37:28.731 Exception while executing function: Functions.TimerTriggerCSharp1. mscorlib: Exception has been thrown by the target of an invocation. f-TimerTriggerCSharp1__-205940111: Could not load file or assembly 'EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' or one of its dependencies. The system cannot find the file specified.

  1. Now edit your Run.csx file to be like this:
using System;

public static void Run(TimerInfo myTimer, TraceWriter log)
{
    log.Info(typeof(MyContext).ToString());    
}

public class MyContext : System.Data.Entity.DbContext
{
}
  1. Save and observe a successful compile.
  2. Run and observe a successful run with no runtime error.

I expect the runtime error in step 10 to not be there. I expect it to successfully run just as it does in step 13.

Hi Justin ,

Can you try to use efconnection builder and prepare the connection string on initialise .

That is something like this

public DB(string connectionString) : base(Getconnection() )

And make a static function namedoes getConnection () returning connectionstring made using entity connection builder.

Thanks

I can confirm I get the same problem.

I put the logic I want my Function to execute in a seperate dll (B) to allow me to use Intellisense and reference them from the function in run.csx (A). When I call a function in (B) which references my domain assembly (C) that uses EF6 I get the above error.

Hi ,

I am using the EF6 and it is working successfully .
Apart from efconnection builder , you also need to copy the ef6 dll in the shared/bin folder and refer the dll / import in your csx file .

These are the snippets of my working code .

public MYDBContext()
: base(GetConnectionString())
{
}

    private static string GetConnectionString()

    {

        const string providerName = "System.Data.SqlClient";
        const string metadata = @"res://*/MYDB.csdl|res://*/MYDB.ssdl|res://*/MYDB.msl";

        string connectString = ConfigurationManager.ConnectionStrings["MYDBContext"].ToString();


        // Initialize the connection string builder for the
        // underlying provider.
        SqlConnectionStringBuilder sqlBuilder = new SqlConnectionStringBuilder(connectString);

        // Set the properties for the data source.
        //sqlBuilder.IntegratedSecurity = true;
        sqlBuilder.MultipleActiveResultSets = true;

        // Build the SqlConnection connection string.
        string providerString = sqlBuilder.ToString();

        // Initialize the EntityConnectionStringBuilder.
        EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();

        //Set the provider name.
        entityBuilder.Provider = providerName;

        // Set the provider-specific connection string.
        entityBuilder.ProviderConnectionString = providerString;

        // Set the Metadata location.
        entityBuilder.Metadata = metadata;

        return entityBuilder.ConnectionString;

    }

here the connection string is set in application settings .

on csx part

using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.ModelConfiguration.Conventions;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Configuration;
using System.IO;
using System.Net.Mail;

using Newtonsoft.Json.Linq;
using Newtonsoft.Json;

public static void Run(string myQueueItem, TraceWriter log)
{

       try
{

//MYDBcontext is being set in application settings on azurefunctions with the connectionstring as value
log.Info(GetConnectionStringVariable("MYDBContext"));
}
catch (System.Exception ex)
{
log.Info($"Error Occured : {ex}");
throw ex;
}

}

public static string GetConnectionStringVariable(string name)
{

return ConfigurationManager.ConnectionStrings[name].ConnectionString;

}

and in the shared folder place these two dlls
EntityFramework.dll
EntityFramework.SqlServer.dll

Thanks

@govindsyadv - thanks, that works! So I assumed that by adding the Entity Framework package to the nuget file in my Functions project it would be enough for my satellite assembly to pick it up. But it isn't, I need to copy the EF dll and all the other dll's my satellite needs for operation. So I just greated a gulp file to copy all of them into the bin folder for my function.

Hopefully references will be something coming soon in the tooling.

@rndthoughts the next version of the VS tooling will have a much richer support for those scenarios. We're also working on enhancing documentation for some of those assembly deployment/reference cases since what we have today is does not clearly document behavior like what you've experienced above (which would be a simple thing to grasp if the documentation covered it)

/cc @lindydonna

@fabiocav Would the improved documentation be handled by https://github.com/Azure/Azure-Functions/issues/113?

Yes, it would.

Stale issue. Closing as there are no remaining follow up items

Was this page helpful?
0 / 5 - 0 ratings