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

发布于 2024-10-24 05:13:03 字数 3860 浏览 2 评论 0原文

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

环境:我有一个 WCF 服务的开发和生产两个环境。我将连接字符串存储在 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);
        }
    }
}

感谢您花时间查看此内容。我已经尽力做到具体和详细,但如果我遗漏了什么,请告诉我。

谢谢, 杰拉尔德

Scenario: I want to dynamically choose the connection string based on the environment that the application is running in.

Environment: I have a two environments Dev and Production for a WCF Service. I store the connection strings in the web.config. When that app starts up set a variable with the correct connection string to use.

Problem:
When the data model is generated it creates 2 files dmMyDataModel.edmx and dmMyDataModel.Designer.cs, in the designer file there are constructors in there that define the connection to the EntityDatabas.

In the code below you can see that I have created a constructor in the service that when the service is called it will set the context to use the right connection string. But only the items that use myContext work correctly (the stored procedures) the querying of the dbMyWebSiteEntities fail in production environment because the still depend on the connection string set in the designer.

I tired setting the logic in the designer but that get wiped out when its re-generated.

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

Thanks for taking the time to look at this. I have tried to be specific and detailed but if I left something out let me know.

Thanks,
Gerald

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

黑寡妇 2024-10-31 05:13:03

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

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

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

我使用 Xml 转换在 .config 文件中为我拥有的每个环境(开发/测试/测试版/产品)设置不同的连接字符串。

The generated class is partial. If you want to add new constructors define another partial class (the same class name and namespace) is a different file and add your constructors there. Your file won't be regenerated. That's what partial keyword is for.

Your new constructor has to be unique - different parameters.

You can also define a static factory method in your partial class which will encapsulate the logic of instantiation.

I set different connection strings in .config files using Xml Transformations for each environment I have (Dev / Test / Beta / Prod).

紫﹏色ふ单纯 2024-10-31 05:13:03

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

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

在这个包装器中,您可以通过多种方式处理不同的逻辑。

HTH。

Best way is to create a wrapper:

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

In this wrapper you can handle the varying logic through a variety of ways.

HTH.

孤独患者 2024-10-31 05:13:03

您可以在 此处找到类似的查询

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

You can find the similar query in the over here

It gives example of using EntityConnectionStringBuilder class in namespace System.Data.Common.DbConnectionStringBuilder

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文