Entity Framework - redundant connection string

后端 未结 4 1726
眼角桃花
眼角桃花 2021-02-08 18:57

I\'m using Entity Framework 4 in my project. The Framework has created its own connection string, so my web.config connectionStrings section file looks following:

相关标签:
4条回答
  • 2021-02-08 19:47
    1. Manualy create DbConnection from ordinary connection string
    2. Manualy create MetadataWorkspace object.
    3. Create EntityConnection using this ctor.
    4. Pass entity connection to ObjectContext constructor.
    0 讨论(0)
  • 2021-02-08 19:48

    Although you can create the connection in code, as @gandjustas points out (+1), you cannot get away from having a connection string or EntityConnection.

    This is because it is not actually redundant. Yes, the database connection part is redundant, and @gandjustas showed you how to remove that redundancy. However, the entity framework connection string also contains information about your model, which is not found anywhere in the connection string you wish to keep. This model information has to come from somewhere. Were you to eliminate the entity framework's connection string and use the parameter list constructor on ObjectContext, you would have eliminated all references to the model.

    0 讨论(0)
  • 2021-02-08 19:53

    I had the same problem. I have solved it by following way:

    I have created two edmx file, but while creating second edmx file, i ignored the connection string to be save in config file. This way my config file will hold only one Connection string. Then i modified following lines in my connection string:

    <add name="MyDbContext" connectionString="metadata=res://*/;provider=System.Data.SqlClient;provider connection string=&quot;data source=abc;initial catalog=mydb;persist security info=True;user id=myuser;password=password;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
    

    Just replace "res://model1.csdl" with "res://*/" and it works like a charm.

    You can specify this connection name in constructor of your dbcontext class like:

    public MyDbContext() : base("name=NameOfYourConnectionString") //  Name of your connection string
    { }
    

    Note: I am using Entity Framework 5.0.

    0 讨论(0)
  • 2021-02-08 19:54

    I'll provide complete implementation I did to resolve this issue (based on gandjustas hints). I've written a simple wrapper for the context, which can be used in the following manner:

    using (var wrapper = new ContextWrapper<VNKEntities>())
    {
        // do your stuff based on wrapper.Context
    }
    

    Type ContextWrapper is a template which simply wraps the context which is just constructed in a slightly other way (using only one connection string) and then exposed by property. Its internal implementation is placed below:

    public class ContextWrapper<TContext> : IDisposable
        where TContext : ObjectContext
    {
        private TContext _context;
        private EntityConnectionManager _manager;
        private bool _disposed;
    
        public ContextWrapper()
            : this(true)
        {
        }
    
        public ContextWrapper(bool lazyLoadingEnabled)
        {
            _disposed = false;
            _manager = new EntityConnectionManager();
            _context = (TContext)Activator.CreateInstance(typeof(TContext), _manager.Connection);  
            _context.ContextOptions.LazyLoadingEnabled = lazyLoadingEnabled;
        }
    
        ~ContextWrapper()
        {
            Dispose(false);
        }
    
        public TContext Context
        {
            get { return _context; }
        }
    
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
    
        }
    
        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    if (_manager != null)
                    {
                        _manager.Dispose();
                        _manager = null;
                    }
                    var ctx = _context as IDisposable;
                    if (ctx != null)
                    {
                        ctx.Dispose();
                        _context = null;
                    }
                }
            }
            _disposed = true;
        }
    }
    

    You can see the usage of custom class named EntityConnectionManager:

    internal class EntityConnectionManager : IDisposable
    {
        private DbConnection _connection;
        private EntityConnection _entityConnection;
    
        private volatile bool _disposed;
    
        public EntityConnectionManager()
        {
            var workspace = new MetadataWorkspace(Setting.MetadataWorkspacePaths.Split('|'), new[] { Assembly.ReflectionOnlyLoad(Setting.MetadataAssemblyNameToConsider) });
    
            _connection = new SqlConnection(Setting.ConnectionString);
            _entityConnection = new EntityConnection(workspace, _connection);
            _disposed = false;
        }
    
        public EntityConnection Connection
        {
            get { return _entityConnection; }
        }
    
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    
        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    if (_connection != null)
                    {
                        _connection.Dispose();
                        _connection = null;
                    }
                    if (_entityConnection != null)
                    {
                        _entityConnection.Dispose();
                        _entityConnection = null;
                    }
                }
            }
            _disposed = true;
        }
    }
    

    So now you can have one connection string:

    <connectionStrings>
      <add name="ApplicationServices" connectionString="data source=localhost;user id=user;pwd=pass;initial catalog=VNK;Pooling=False;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />    
    </connectionStrings>
    

    and metadata defined in app settings section (the second key points to assembly where your domain model is actually stored):

    <appSettings>
      <add key="MetadataWorkspacePaths" value="res://*/VNKModel.csdl|res://*/VNKModel.ssdl|res://*/VNKModel.msl" />
      <add key="MetadataAssemblyNameToConsider" value="VNK.Models" />
    </appSettings>
    

    The logic for type Setting is straightforward, as it just pulls out the settings from configuration file.

    0 讨论(0)
提交回复
热议问题