简体   繁体   中英

Override DbContext EF6

I'm trying to understand how to dynamically create the connection string for my DbContext, but my application says it has no connection string in the app.config (and that's correct because I don't want to use it in the app.config or web.config). This is what I have:

In my solution I have a project called InterfaceApp. It is a ASP.NET MVC 5 application. When I put my connection string in the web.config all seems to be working fine.

In my solution I have an other project called InterfaceApp.Connector.Erp1. Here I want to connect to an ERP application and fetch some items. So in my repository I have:

namespace InterfaceApp.Connector.Erp1.Repository
{
    internal class ItemRepository : IItemRepository
    {
        public IEnumerable<Item> Items
        {
            get
            {
                List<Item> items = new List<Item>();

                using (Models.Entities context = new Models.Entities())
                {
                     var itemList = context.Items.ToList();
                    foreach(var item in itemList)
                    {
                        items.Add(new Item() { Id = item.ID, Description = item.Description, ItemCode = item.ItemCode });
                    }
                }

                return items.ToList();
            }
        }
    }
}

I've created a partial class to connect to the database:

namespace InterfaceApp.Connector.Erp1.Models
{
    public partial class Entities
    {
        public Entities(string connectionString)
            : base(ConnectionString())
        {
        }


        private static string ConnectionString()
        {
            SqlConnectionStringBuilder sqlBuilder = new SqlConnectionStringBuilder
            {
                DataSource = "MyServer", //When this works it will be dynamic
                InitialCatalog = "XXX", //When this works it will be dynamic
                PersistSecurityInfo = true,
                IntegratedSecurity = true,
                MultipleActiveResultSets = true,

            };

            var entityConnectionStringBuilder = new EntityConnectionStringBuilder
            {
                Provider = "System.Data.SqlClient",
                Metadata = "res://*/Models.Erp1Model.csdl|res://*/Models.Erp1Model.ssdl|res://*/Erp1Model.msl",
                ProviderConnectionString = sqlBuilder.ConnectionString

            };

            return entityConnectionStringBuilder.ConnectionString;

        }
    }
}

The Context class that is auto-generated by EF6 (Db First) looks like this:

namespace InterfaceApp.Connector.Erp1.Models
{
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;

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

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

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

When I run my application, the debugger stops at the auto-generated class, but not at my partial class. Because it cannot find the connection string Entities in my app.config and web.config it generates an error saying that the connection string is not found in the application config file. What am I doing wrong?

When you are calling the DbContext, you're calling the empty constructor ( new Models.Entities() ). Thus, it will call the auto-generated DbContext. If you want to call your partial class, you need to call it explicitly with the parameter.

Remember when you create a partial class, the compiler merges them, so you have this when compiled :

public partial class Entities : DbContext
{
    public Entities()
        : base("name=Entities")
    {
    }
    public Entities(string connectionString)
        : base(ConnectionString())
    {
    }


    private static string ConnectionString()
    {
        SqlConnectionStringBuilder sqlBuilder = new SqlConnectionStringBuilder
        {
            DataSource = "MyServer", //When this works it will be dynamic
            InitialCatalog = "XXX", //When this works it will be dynamic
            PersistSecurityInfo = true,
            IntegratedSecurity = true,
            MultipleActiveResultSets = true,

        };

        var entityConnectionStringBuilder = new EntityConnectionStringBuilder
        {
            Provider = "System.Data.SqlClient",
            Metadata = "res://*/Models.Erp1Model.csdl|res://*/Models.Erp1Model.ssdl|res://*/Erp1Model.msl",
            ProviderConnectionString = sqlBuilder.ConnectionString

        };

        return entityConnectionStringBuilder.ConnectionString;

    }

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

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

What you probably need aa method to create your DbContext and call it instead of calling a new DbContext.

public static Entities Create()
{
    return new Entities(ConnectionString());
}

Then you can use it this way :

using (var context = Entities.Create())
{
     //...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM