繁体   English   中英

实体框架 - 冗余连接字符串

[英]Entity Framework - redundant connection string

我在我的项目中使用Entity Framework 4。 框架已创建自己的连接字符串,因此我的web.config connectionStrings部分文件如下所示:

  <connectionStrings>
    <add name="ApplicationServices" connectionString="data source=localhost;user id=user;pwd=pass;initial catalog=VNK" providerName="System.Data.SqlClient" />    
    <add name="VNKEntities" connectionString="metadata=res://*/VNKModel.csdl|res://*/VNKModel.ssdl|res://*/VNKModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=localhost;Initial Catalog=VNK;User ID=user;Password=pass;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>

名为ApplicationServices的第一个连接字符串是我原来的连接字符串。 第二个名为VNKEntities在生成模型时创建。

当我检查生成的* .edmx文件时,我发现此模型正在引用其连接字符串,如下所示:

    /// <summary>
    /// Initializes a new VNKEntities object using the connection string found in the 'VNKEntities' section of the application configuration file.
    /// </summary>
    public VNKEntities() : base("name=VNKEntities", "VNKEntities")
    {
        this.ContextOptions.LazyLoadingEnabled = true;
        OnContextCreated();
    }

我的问题是如何摆脱VNKEntities连接字符串,只留下我将从我的模型引用的ApplicationServices 我想只有一个连接字符串到数据库,因为我只使用一个数据库(将name=VNKEntities的构造函数参数替换为name=ApplicationServices不起作用)。

问候

虽然您可以在代码中创建连接,但是@gandjustas指出(+1),您无法摆脱连接字符串或EntityConnection

这是因为它实际上并不多余 是的,数据库连接部分是冗余的,@ gjjasas向您展示了如何删除冗余。 但是,实体框架连接字符串还包含有关模型的信息,这些信息在您希望保留的连接字符串中找不到。 此模型信息必须来自某个地方。 如果要消除实体框架的连接字符串并使用ObjectContext上的参数列表构造函数,您将消除对模型的所有引用。

  1. Manualy从普通连接字符串创建DbConnection
  2. Manualy创建MetadataWorkspace对象。
  3. 使用此ctor创建EntityConnection
  4. 将实体连接传递给ObjectContext构造函数。

我有同样的问题。 我通过以下方式解决了它:

我创建了两个edmx文件,但在创建第二个edmx文件时,我忽略了要在配置文件中保存的连接字符串。 这样我的配置文件将只保存一个连接字符串。 然后我在我的连接字符串中修改了以下行:

<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" />

只需将“res://model1.csdl”替换为“res:// * /” ,它就像魅力一样。

您可以在dbcontext类的构造函数中指定此连接名称,如:

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

注意:我正在使用Entity Framework 5.0。

我将提供完整的实现来解决此问题(基于gandjustas提示)。 我为上下文编写了一个简单的包装器,可以按以下方式使用:

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

类型ContextWrapper是一个模板,它简单地包装刚刚以其他方式构造的上下文(仅使用一个连接字符串),然后通过属性公开。 其内部实施如下:

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;
    }
}

您可以看到名为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;
    }
}

所以现在你可以有一个连接字符串:

<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>

和应用程序设置部分中定义的元数据(第二个关键点指向实际存储域模型的程序集):

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

类型Setting的逻辑很简单,因为它只是从配置文件中提取设置。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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