22

I have a dll that uses the Entity Framework 6 to do some database operations. I'm using a database first approach. The model and everything concerning the Entity Framework, like the connection string in the App.config, were created via the wizzard in Visual Studio.

So I compiled the dll and put it together with the corresponding .config in the folder where the application using the dll expects it.

Everything works fine until I get to the point where an actual database call is made. There I get the error:

Cannot find connection string for MyDatabaseEntity

The automatically generated connectionstring is, as I said, in the config file of the dll. I cannot change the App.config of the application. But the application hands over an object that has all the information I need to build the connection string myself. So I'm looking for a way to set the connection string in the code without relying on a config file. All the tutorials I find for a database first approach use this method though. I found a post here that says to simply give the connection string as a parameter when creating the Object like

MyDatabaseEntities = new MyDatabaseEntities(dbConnect);

but ´MyDatabaseEntities´ doesn't have a constructor that takes any parameters

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

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }

    public virtual DbSet<MyTable> MyTable { get; set; }
}
Alexander Derck
  • 13,818
  • 5
  • 54
  • 76
FNR
  • 489
  • 1
  • 4
  • 17

5 Answers5

23

How about:

public partial class MyDatabaseEntities : DbContext
{
public MyDatabaseEntities(string connectionString)
    : base(connectionString)
{
}

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    throw new UnintentionalCodeFirstException();
}

public virtual DbSet<MyTable> MyTable { get; set; }

}

Then initialize your database like you did before:

string myConnectionString = "...";
MyDatabaseEntities = new MyDatabaseEntities(myConnectionString);
Alexander Derck
  • 13,818
  • 5
  • 54
  • 76
  • 2
    I wasn't aware that the string at base() was the connection string. Thank you , that did it. – FNR Dec 18 '15 at 08:24
  • Yes, it tries to find the connectionstring with the name specified in the parenthesis in the config file of your startup project – Alexander Derck Dec 18 '15 at 08:31
  • I have set connecting stirng like this: string connection = @"metadata=res://*/ShopModel.csdl|res://*/ShopModel.ssdl|res://*/ShopModel.msl;provider=System.Data.SqlClient;provider connection string="data source=SIPL35\SQL2016;initial catalog=Join8ShopDB2;user id=Sa;password=Sa123!@#;MultipleActiveResultSets=True;App=EntityFramework""; Join8ShopDBEntities dbContext = new Join8ShopDBEntities(connection); but it is giving me data source keyword not identified exception – Dev-Systematix Feb 20 '17 at 13:02
  • 1
    @Dev-Systematix You can't used `&quot`, use single quotes `'` instead. – Alexander Derck Feb 20 '17 at 13:13
  • Here above answer connecting string is not from code, this code using connection string from config file. – Dev-Systematix Feb 20 '17 at 13:55
  • @Dev-Systematix `string connection = "..."` that's not using config file :p – Alexander Derck Feb 20 '17 at 14:22
  • 1
    If we will not use EntityConnectionStringBuilder then it will not identify Data Source keyword and raise exception – Dev-Systematix Feb 20 '17 at 15:11
  • 1
    I tried this but got an exception: `UnintentionalCodeFirstException: 'The context is being used in Code First mode with code that was generated from an EDMX file for either Database First or Model First development. This will not work correct ...` and to get rid of that, I delete the line: `throw new UnintentionalCodeFirstException();`, but there is other problem, which is every time I `Update model from database` the partial `DbContext` class is being regenerated and I lose modifications – Ahmed Suror Jun 06 '20 at 13:51
  • @AhmedSuror, Did you solve this issue? if so, you can guide us by posting your answer herel. – SaddamBinSyed Mar 10 '21 at 13:20
  • @SaddamBinSyed Yes, apply this answer by creating a new class file and dclare it as partial with the constructor and make the connection string like this answer https://stackoverflow.com/a/45913703/1655837 To do that, copy the connection string from your model and use it and replace " with "" – Ahmed Suror Mar 10 '21 at 20:00
  • If come by this post and you are using EF Core and not EF, I wrote a post on that here: https://peterdaugaardrasmussen.com/2022/04/09/entity-framework-how-to-set-the-connection-string-of-the-dbcontext/ – Peter Rasmussen Apr 10 '22 at 08:09
9

I had the similar issue. My Edmx and App.Config was in a different project. My startup project was different, had 3 different connection strings, we need to choose one on the fly depending on the environment. So couldn't use a fixed connection string. I created a partial class overload of the Context.cs using the same namespace. Following was my default Context.cs;

namespace CW.Repository.DBModel
{

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

      protected override void OnModelCreating(DbModelBuilder modelBuilder)
      {
        throw new UnintentionalCodeFirstException();
      }
  ...
  ...
  }
}

My partial class overload;

namespace CW.Repository.DBModel
{
    public partial class CWEntities : DbContext
    {
        public CWEntities(string ConnectionString)
            : base(ConnectionString)
        {
        }        
    }
}

Lastly, as my connection strings were not for EF, I converted them to a EF connection string.

public static string GetEntityConnectionString(string connectionString)
    {
        var entityBuilder = new EntityConnectionStringBuilder();

        // WARNING
        // Check app config and set the appropriate DBModel
        entityBuilder.Provider = "System.Data.SqlClient";
        entityBuilder.ProviderConnectionString = connectionString + ";MultipleActiveResultSets=True;App=EntityFramework;";
        entityBuilder.Metadata = @"res://*/DBModel.CWDB.csdl|res://*/DBModel.CWDB.ssdl|res://*/DBModel.CWDB.msl";

        return entityBuilder.ToString();
    }

Lastly, the calling

var Entity = new CWEntities(CWUtilities.GetEntityConnectionString(ConnectionString));
Mahib
  • 3,977
  • 5
  • 53
  • 62
  • 1
    thanks. It could be better if you mention you partial class overload is on another file instead of your default Context.cs as it is auto-generated by Visual Studio and may be overwritten by Visual Studio. – zagZzig Aug 14 '18 at 00:19
  • @Mahib, I have tried your steps but for the first time calling DB proc is working fine but next time when i call next DbProc its failing with Timeout related error. any advise appreciated. – SaddamBinSyed Mar 10 '21 at 13:29
5

I got this solution using below code, I can hardcode connection string using C# code without using config file.

 public class SingleConnection
    {
        private SingleConnection() { }
        private static SingleConnection _ConsString = null;
        private String _String = null;

        public static string ConString
        {
            get
            {
                if (_ConsString == null)
                {
                    _ConsString = new SingleConnection { _String = SingleConnection.Connect() };
                    return _ConsString._String;
                }
                else
                    return _ConsString._String;
            }
        }

        public static string Connect()
        {
            //Build an SQL connection string
            SqlConnectionStringBuilder sqlString = new SqlConnectionStringBuilder()
            {
                DataSource = "SIPL35\\SQL2016".ToString(), // Server name
                InitialCatalog = "Join8ShopDB",  //Database
                UserID = "Sa",         //Username
                Password = "Sa123!@#",  //Password
            };
            //Build an Entity Framework connection string
            EntityConnectionStringBuilder entityString = new EntityConnectionStringBuilder()
            {
                Provider = "System.Data.SqlClient",
                Metadata = "res://*/ShopModel.csdl|res://*/ShopModel.ssdl|res://*/ShopModel.msl",
                ProviderConnectionString = @"data source=SIPL35\SQL2016;initial catalog=Join8ShopDB2;user id=Sa;password=Sa123!@#;"// sqlString.ToString()
            };
            return entityString.ConnectionString;
        }

and using DbContext using like this:

Join8ShopDBEntities dbContext = new Join8ShopDBEntities(SingleConnection.ConString);
Dev-Systematix
  • 439
  • 6
  • 26
0

Thanks a lot . I changed little for Code First EF6.

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.Entity.Core.EntityClient;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Data
{
    public class SingleConnection
    {
        private SingleConnection() { }
        private static SingleConnection _ConsString = null;
        private String _String = null;

        public static string ConString
        {
            get
            {
                if (_ConsString == null)
                {
                    _ConsString = new SingleConnection { _String = SingleConnection.Connect() };
                    return _ConsString._String;
                }
                else
                    return _ConsString._String;
            }
        }

        public static string Connect()
        {
            string conString = ConfigurationManager.ConnectionStrings["YourConnectionStringsName"].ConnectionString;

            if (conString.ToLower().StartsWith("metadata="))
            {
                System.Data.Entity.Core.EntityClient.EntityConnectionStringBuilder efBuilder = new System.Data.Entity.Core.EntityClient.EntityConnectionStringBuilder(conString);
                conString = efBuilder.ProviderConnectionString;
            }

            SqlConnectionStringBuilder cns = new SqlConnectionStringBuilder(conString);
            string dataSource = cns.DataSource;


            SqlConnectionStringBuilder sqlString = new SqlConnectionStringBuilder()
            {
                DataSource = cns.DataSource, // Server name
                InitialCatalog = cns.InitialCatalog,  //Database
                UserID = cns.UserID,         //Username
                Password = cns.Password,  //Password,
                MultipleActiveResultSets = true,
                ApplicationName = "EntityFramework",

            };
            //Build an Entity Framework connection string
            EntityConnectionStringBuilder entityString = new EntityConnectionStringBuilder()
            {
                Provider = "System.Data.SqlClient",
                Metadata = "res://*",
                ProviderConnectionString = sqlString.ToString()
            };
            return entityString.ConnectionString;
        }
    }
}
0

You can use singleton patter for it . For example

private YouurDBContext context;

    public YouurDBContext Context
    {
        get
        {
            if (context==null)
            {
                context = new YouurDBContext();
            }
            return context;

        }
        set { context = value; }
    }