如何在自动生成的实体模型代码中覆盖连接字符串

时间:2011-03-16 21:25:13

标签: asp.net wcf entity-framework connection-string

场景:我想根据运行应用程序的环境动态选择连接字符串。

环境:我有一个针对WCF服务的两个环境Dev和Production。我将连接字符串存储在web.config中。当该应用程序启动时,使用正确的连接字符串设置变量。

问题: 生成数据模型时,它会在设计器文件中创建2个文件dmMyDataModel.edmx和dmMyDataModel.Designer.cs,其中有构造函数,用于定义与EntityDatabas的连接。

在下面的代码中,您可以看到我在服务中创建了一个构造函数,当调用该服务时,它将设置上下文以使用正确的连接字符串。但是只有使用myContext的项目(存储过程)才能正确查询dbMyWebSiteEntities在生产环境中失败,因为仍然依赖于设计器中设置的连接字符串。

我厌倦了在设计师中设置逻辑但在重新生成时会被消除。

dmMyDataModel.Designer.cs

using System;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using System.Data.EntityClient;
using System.ComponentModel;
using System.Xml.Serialization;
using System.Runtime.Serialization;

[assembly: EdmSchemaAttribute()]

namespace MyWebSite.Services
{
    #region Contexts

    /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    public partial class dbMyWebSiteEntities : ObjectContext
    {
        #region Constructors

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

        /// <summary>
        /// Initialize a new dbMyWebSiteEntities object.
        /// </summary>
        public dbMyWebSiteEntities(string connectionString) : base(connectionString, "dbMyWebSiteEntities")
        {
            this.ContextOptions.LazyLoadingEnabled = true;
            OnContextCreated();
        }
        /// <summary>
        /// Initialize a new dbMyWebSiteEntities object.
        /// </summary>
        public dbMyWebSiteEntities(EntityConnection connection) : base(connection, "dbMyWebSiteEntities")
        {
            this.ContextOptions.LazyLoadingEnabled = true;
            OnContextCreated();
        }

        #endregion
        ...
    }

MyWebSiteData.svc.cs

using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Data.Services.Common;
using System.Linq;
using System.ServiceModel.Web;
using System.Web;
using System.ServiceModel.Activation;
using System.ServiceModel;
using System.Data.EntityClient;
using System.Configuration;
using System.Data.Objects;

namespace MyWebSite.Services
{
    public class MyWebSiteData : DataService<dbMyWebSiteEntities>
    {
        private dbMyWebSiteEntities myContext;

        public static void InitializeService(DataServiceConfiguration config)
        {
            config.UseVerboseErrors = true; 
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
            config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
            config.SetEntitySetPageSize("*", 25);

            config.SetServiceOperationAccessRule("mar_getAllByKey", ServiceOperationRights.AllRead);
        }

        //Constructor to override the connection string used in the dmMyDataModel.Designer.cs
        public MyWebSiteData()
        {
            //sets the connetion string and appends the environment so it will pull the correct one from the web.config
            EntityConnection conn = new EntityConnection("name=dbMyWebSiteEntities" + HttpContext.Current.Application["Environment"]);
            myContext = new dbMyWebSiteEntities(conn);
        }

        //This returns the data from the stored procedures
        [WebGet]
        public ObjectResult<myTable> mar_getAllByKey(string key)
        {
            return myContext.mar_getAllByKey(key);
        }
    }
}

感谢您抽出宝贵时间来研究这个问题。我试图具体而详细,但如果我遗漏了一些东西,请告诉我。

谢谢, 杰拉德

3 个答案:

答案 0 :(得分:4)

生成的类为partial。如果要添加新的构造函数,则定义另一个部分类(相同的类名和命名空间)是不同的文件,并在那里添加构造函数。您的文件将不会重新生成。这就是partial关键字的用途。

您的新构造函数必须是唯一的 - 不同的参数。

您还可以在分部类中定义静态工厂方法,该方法将封装实例化的逻辑。

我在.config文件中使用Xml Transformations为我拥有的每个环境设置了不同的连接字符串(Dev / Test / Beta / Prod)。

答案 1 :(得分:0)

最好的方法是创建一个包装器:

public static class DBContextCreator
{
   public static MyDBContext Create()
   {
        return new MyDBContext(/* pass in connection of choice here */);
   }
}

在这个包装器中,您可以通过各种方式处理变化的逻辑。

HTH。

答案 2 :(得分:0)

您可以在here

上找到类似的查询

它给出了在命名空间System.Data.Common.DbConnectionStringBuilder中使用EntityConnectionStringBuilder类的示例