Jim
Jim

Reputation: 2828

Database first and Entity Framework Dynamic Connection String

In my WPF app (database-first EF) I need to provide a way to the user to update / modify the database connection string (azure located) at runtime. I am extending the autogenerated partial class of MyContext by adding the following method. However I get an error

A method of same signature already exists

What is the correct procedure of adding dynamically connection string?

Thx

Error message:

Type 'MyServDataCollection.Models.MyContext' already defines a member called 'MyContext' with the same parameter types

MyContext class

using System.Data.Entity;
using System.Data.Entity.Core.EntityClient;

public partial class MyContext : DbContext
{
    public MyContext() : base(GetConnectionString())
    {
    }

    private static string GetConnectionString()
    {
        var model = "MyServDataCollectionModel";
        var providerConnectionString = "metadata=res://*/Models.MyServDataCollectionModel.csdl|res://*/Models.MyServDataCollectionModel.ssdl|res://*/Models.MyServDataCollectionModel.msl;provider=System.Data.SqlClient;provider connection string="data source=xxx.database.windows.net;initial catalog=xxxx;persist security info=True;user id=xxxxxxx;password=xxxxx;MultipleActiveResultSets=True;App=EntityFramework"";

        var efConnection = new EntityConnectionStringBuilder();
        efConnection.Provider = "System.Data.SqlClient";
        efConnection.ProviderConnectionString = providerConnectionString;

        // based on whether you choose to supply the app.config connection string to the constructor
        efConnection.Metadata = string.Format("res://*/Model.{0}.csdl|res://*/Model.{0}.ssdl|res://*/Model.{0}.msl", model);
        // Make sure the "res://*/..." matches what's already in your config file.
        return efConnection.ToString();
    }

Upvotes: 0

Views: 515

Answers (2)

Toby Crawford
Toby Crawford

Reputation: 827

If you wanted to allow consuming code to continue using a parameterless constructor to create instances of your DBContext, you could amend the T4 template to ensure the auto generated class does not define a parameterless constructor:

Remove the following from the MyContext.Context.tt file:

    public <#=code.Escape(container)#>()
        : base("name=<#=container.Name#>")
    {
    <#

    if (!loader.IsLazyLoadingEnabled(container))
    {
    #>
        this.Configuration.LazyLoadingEnabled = false;
    <#

    }

foreach (var entitySet in container.BaseEntitySets.OfType<EntitySet>())
{
    // Note: the DbSet members are defined below such that the getter and
    // setter always have the same accessibility as the DbSet definition
    if (Accessibility.ForReadOnlyProperty(entitySet) != "public")
    {
    #>
            <#=codeStringGenerator.DbSetInitializer(entitySet)#>
    <#
        }
    }
    #>
    }

This will allow your partial class to work as you expect.

Upvotes: 1

Stefan Babos
Stefan Babos

Reputation: 296

This error message is correct. Parameterless constructor is already contained in generated partial class(generated by Visual Studio). To connect using customized connection string you simply call constructor with connection string(or configuration key - see help). I think this constructor is already generated but if is not, then you can simply create it adding this code to your partial class:

public partial class MyContext : DbContext
{
  public MyContext(string connectionStringOrKey)
    : base(connectionStringOrKey)
  {
  }
}

Method GetConnectionString() you can create as is only with public instead private.
Then simply call

MyContext myCtx = new MyContext(MyConnection.GetConnectionString()) 

for example. Another solution would be to modify your partial class with add static method CreateMyContext:

public partial class MyContext : DbContext
{
  private static string GetConnectionString()
  {
  }

  public static MyConnection CreateMyContext()
  {
    return new MyContext(MyContext.GetConnectionString());
  }
}

In this case, but would probably be better to put these methods to another class(extension class ?).

Upvotes: 1

Related Questions