简体   繁体   English

将连接字符串传递给实体框架 6

[英]Passing Connection String to Entity Framework 6

I am using EF6 in a class library (database first)我在类库中使用 EF6(数据库优先)

When I followed the wizard and added my tables I selected not to store the connections string in the app.config and that I would send the connections string.当我按照向导添加我的表时,我选择不在 app.config 中存储连接字符串,而是发送连接字符串。

I haven't done this before.我以前没有这样做过。 Normally I select to put the connection string in the app.config file.通常我选择将连接字符串放在 app.config 文件中。

I am now completely stumped how I actually call a function and pass the connection string to it.我现在完全难倒我如何实际调用一个函数并将连接字符串传递给它。

Below are what I hope are relevant code snippets from my solution.以下是我希望是我的解决方案中的相关代码片段。

In the app.config - EF automatically added this:在 app.config - EF 自动添加了这个:

<connectionStrings>
<add name="cerviondemoEntities" connectionString="metadata=res://*/DatabaseModel.cervionEDM.csdl|res://*/DatabaseModel.cervionEDM.ssdl|res://*/DatabaseModel.cervionEDM.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=DEVBOX;initial catalog=cerviondemo;user id=sa;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
</connectionStrings>

My auto generated context class looks like this:我自动生成的上下文类如下所示:

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Manual changes to this file may cause unexpected behavior in your application.
//     Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace CervionFunctions.DatabaseModel
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;

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

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

    public virtual DbSet<Customer> Customers { get; set; }
    public virtual DbSet<Ticket> Tickets { get; set; }
}
}

Ultimately, I am trying to call the following test function:最终,我试图调用以下测试函数:

public static List<Customer> customersToUpdate()
    {
        cerviondemoEntities db;

        using (db = new DatabaseModel.cerviondemoEntities())
        {
            var result = from customers in db.Customers
                         select customers;

            return result.ToList();
        }
    }

I cannot work out how to send the connection string to that function :(我不知道如何将连接字符串发送到该函数:(

Any help would be greatly appreciated!任何帮助将不胜感激!

By convention, Entity Framework takes the connection string that has the same name as the context.按照惯例,实体框架采用与上下文同名的连接字符串。 For example:例如:

public cerviondemoEntities()
    : base("name=cerviondemoEntities")
{
}

The DbContext class has a constructor that takes a connection string. DbContext 类有一个接受连接字符串的构造函数。 You can add another constructor that takes a connectionstring as a parameter and pass it to the base constructor.您可以添加另一个将连接字符串作为参数的构造函数,并将其传递给基本构造函数。

public cerviondemoEntities(string connectionString) : base(connectionString)
{
}

Be sure to create a partial class so your added constructor is not overwritten.一定要创建一个分部类,这样你添加的构造函数就不会被覆盖。

Sample ConnectionString:示例连接字符串:

<connectionStrings>
    <add name="cerviondemoEntities" connectionString="data source=server\database;initial catalog=catalog;persist security info=True;user id=user;password=password;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" /> 
</connectionStrings>

I had this issue as well and used the method from Daniel in the comments.我也有这个问题,并在评论中使用了 Daniel 的方法。

Alternatively, you can add it to the .tt file instead of creating another file and using 'partial' – Daniel K Dec 9 '16 at 19:16或者,您可以将其添加到 .tt 文件中,而不是创建另一个文件并使用“部分” – Daniel K 2016 年 12 月 9 日 19:16

Update *.Context.tt File更新 *.Context.tt 文件

just replace the lines...只需更换线条...

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

with the following...与以下...

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

public <#=code.Escape(container)#>(String nameOrConnectionString)
    : base(nameOrConnectionString)
{

I hope this helps.我希望这有帮助。

You need to introduce another constructor in your context that is expecting a string connectionString argument and make it call base(string nameOrConnectionString) :您需要在您的上下文中引入另一个需要string connectionString参数的构造函数,并使其调用base(string nameOrConnectionString)

public cerviondemoEntities(string connectionString) : base(connectionString)
{
}

I have used the connection string like this, entity connection string instead of normal connection string我已经使用了这样的连接字符串,实体连接字符串而不是普通连接字符串

  SqlConnectionStringBuilder sqlString = new SqlConnectionStringBuilder()
        {
    DataSource = "SOURAV-PC", // Server name
    InitialCatalog = "efDB",  //Database
            UserID = "sourav",         //Username
            Password = "mypassword",  //Password
        };
        //Build an Entity Framework connection string

        EntityConnectionStringBuilder entityString = new EntityConnectionStringBuilder()
        {
            Provider = "System.Data.SqlClient",
            Metadata =   "res://*/testModel.csdl|res://*/testModel.ssdl|res://*/testModel.msl",
            ProviderConnectionString = sqlString.ToString()
        };
        return entityString.ConnectionString;
    }

So much better way to do this.更好的方法来做到这一点。 The issue with any change of the diagram or properties the context.cs is rewritten.重写 context.cs 的图表或属性的任何更改的问题。 The clue is that all of the files are written as partial class objects.线索是所有文件都写为部分类对象。 So, in order not to need to rewrite the context every time you change the entity framework, add a new cs file outside the EntityFramework edmx with a partial class with just the snippets discussed in previous posts.因此,为了不需要在每次更改实体框架时都重写上下文,请在 EntityFramework edmx 之外添加一个新的 cs 文件,其中包含一个仅包含之前帖子中讨论的片段的部分类。

    public partial class cerviondemoEntities
    {
       public cerviondemoEntities(string connectionString):base(connectionString){}
    }

This was kind of discussed in the most approved post, but it was easy to glance over.这在最受认可的帖子中讨论过,但很容易浏览。 This should stop your code from not working if you change the EntityFramework properties.如果您更改 EntityFramework 属性,这应该会阻止您的代码不起作用。 This was important to me because my application needed to connect to remote SQL databases.这对我很重要,因为我的应用程序需要连接到远程 SQL 数据库。

The problem with many approaches shown above (apart from Ian Covill) is that whenever some changes are made in the database and the corresponding model updated, all changes are lost (example, another constructor with parameter).上面显示的许多方法(除了 Ian Covill 之外)的问题是,每当在数据库中进行一些更改并更新相应的模型时,所有更改都会丢失(例如,另一个带有参数的构造函数)。

Hence, another approach, very similar proposed by Ian Covill, can be used.因此,可以使用与 Ian Covill 提出的非常相似的另一种方法。 In my case, I have to choose between development and production database (identical ones).就我而言,我必须在开发和生产数据库(相同的数据库)之间进行选择。

In App.config or web.config在 App.config 或 web.config

<add name="MyEntities" connectionString="metadata=res://*/Infrastructure.DAL.MyDal.csdl|res://*/Infrastructure.DAL.MyDal.ssdl|res://*/Infrastructure.DAL.MyDal.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=192.168.0.1;initial catalog=MyDBName;user id=user;password=&quot;password&quot;;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
<add name="MyEntities_TEST" connectionString="metadata=res://*/Infrastructure.DAL.MyDal.csdl|res://*/Infrastructure.DAL.MyDal.ssdl|res://*/Infrastructure.DAL.MyDal.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=192.168.0.1;initial catalog=My_TEST_DBName;user id=user;password=&quot;password&quot;;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />

Just Outside of *.edmx but on same folder, create a partial class having same name as EntityFramework entity name.在 *.edmx 之外但在同一文件夹中,创建一个与 EntityFramework 实体名称同名的部分类。

public MyEntities(string conStr) : base("name=" + conStr)
{           
}

Now, we can pass our test or production database connection string name.现在,我们可以传递我们的测试或生产数据库连接字符串名称。 Create a partial class (not necessarily) so that you can call this static method to get connection string for correct database based on pre-processor directive.创建一个分部类(不一定),以便您可以调用此静态方法以根据预处理器指令获取正确数据库的连接字符串。

public partial class TestOrProductionDBSelector
{
    public static MyEntities GetTestOrProductionEntity()
    {
#if DEBUG
         return new MyEntities("MyEntities_TEST");
#else
    //ok without param as default is production
        return new MyEntities(); 
#endif
    }
}

Now, the static function GetTestOrProductionEntity() can be called from anywhere and it will call the appropriate connection string based on pre-processor directive selected.现在,可以从任何地方调用静态函数GetTestOrProductionEntity() ,它将根据所选的预处理器指令调用适当的连接字符串。

Hopefully, this helps someone.希望这对某人有所帮助。 The big advantage of this approach is the auto-generated *.Context.cs (inside *.edmx) will remain intact and risk of custom code inside it being overwritten is eliminated.这种方法的一大优势是自动生成的 *.Context.cs(在 *.edmx 中)将保持不变,并且消除了其中的自定义代码被覆盖的风险。

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

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