覆盖代码生成的DbContext构造函数

我确定我在某个阶段之前已经做过这个,但我现在还不清楚怎么做! 我的情景:

// This is generated from EDMX public partial class HOLDbEntities : DbContext { public HOLDbEntities() : base("name=HOLDbEntities") { } } 

现在,我希望这个连接字符串很容易更改(我想从HOLDbEntities实现),所以我需要覆盖这个构造函数。

我试过了:

 public partial class HOLDbEntities { private const string _contextName = "HOLDbEntities"; public static string ContextName { get { return _contextName; } } public HOLDbEntities() : base(ContextName) { } } 

但这会引发一个错误:

HOLDbEntities已经定义了一个名为“HOLDbEntities”的成员,它具有相同的参数类型。

我可以理解为什么会出现这种错误,但是为了做我想要实现的目标,我将如何阻止构造函数首先自动生成?

我能建议的最好的是工厂方法:

 private HOLDbEntities(string contextName) : base(contextName) { } public static HOLDbEntities Create() { return new HOLDbEntities(ContextName); } 

并使用HOLDbEntities.Create()而不是new HOLDbEntities()

我对之前接受的答案进行了投票,因为这是一种相当优雅的方式。 然而,另一种方法是修改生成dbContext类的T4模板。

首先使用EF DB时,你有一个.edmx文件,然后你有一个[Entity] .Context.tt文件。 进入该文件并删除(或修改)以下代码:

 public <#=code.Escape(container)#>() : base("name=<#=container.Name#>") { <# if (!loader.IsLazyLoadingEnabled(container)) { #> this.Configuration.LazyLoadingEnabled = false; <# } foreach (var entitySet in container.BaseEntitySets.OfType()) { // Note: the DbSet members are defined below such that the getter and // setter always have the same accessibility as the DbSet definition if (Accessibility.ForReadOnlyProperty(entitySet) != "public") { #> <#=codeStringGenerator.DbSetInitializer(entitySet)#> <# } } #> 

现在您的上下文类将在没有构造函数的情况下生成,因此您应该能够在扩展类中创建一个。

我更改了context.tt,如下所示:

 <#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext { public <#=code.Escape(container)#>() : base("name=<#=container.Name#>") { <# if (!loader.IsLazyLoadingEnabled(container)) { #> this.Configuration.LazyLoadingEnabled = false; <# } foreach (var entitySet in container.BaseEntitySets.OfType()) { // Note: the DbSet members are defined below such that the getter and // setter always have the same accessibility as the DbSet definition if (Accessibility.ForReadOnlyProperty(entitySet) != "public") { #> <#=codeStringGenerator.DbSetInitializer(entitySet)#> <# } } #> var Method = (typeof(Entities)).GetMethods(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).FirstOrDefault(x => x.Name == "OnModelConstructed"); if (Method!=null) Method.Invoke(this,null); } 

所以我可以在上下文的部分类中声明一个OnModelConstructed方法。

这是我解决问题的方法。 我按照Dylan Hayes的建议编辑了TT文件,并用自己的构造函数替换了构造函数。 就我而言,我只需要更改某些模式的模式名称。 我在配置文件中设置了一个变量,告诉我我所处的环境并使用了正确的模式。

 using System.Configuration; using System.Data.Entity; using System.Data.Entity.Core.Mapping; using System.Data.Entity.Core.Metadata.Edm; using System.Data.Entity.Core.Objects; using System.Data.Entity.Infrastructure; using System.Reflection; using System.Xml; namespace WS.Framework.WSJDEData { public partial class WSJDE : DbContext { public WSJDE() : base("name=WSJDE") { ObjectContext context = (this as IObjectContextAdapter).ObjectContext; string environment = ConfigurationManager.AppSettings.Get("Environment"); const string devCTL = "TESTCTL"; const string devDTA = "TESTDTA"; const string qaCTL = "CRPCTL"; const string qaDTA = "CRPDTA"; const string prodCTL = "PRODCTL"; const string prodDTA = "PRODDTA"; var x = Assembly.GetExecutingAssembly().GetManifestResourceStream("WSJDEData.WSJDE.ssdl"); XmlReader[] sReaders = new XmlReader[] { XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream("WSJDEData.WSJDE.ssdl")) }; XmlReader[] mReaders = new XmlReader[] {XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream("WSJDEData.WSJDE.msl"))}; StoreItemCollection sCollection = new StoreItemCollection(sReaders); ObjectContext objContext = ((IObjectContextAdapter) context).ObjectContext; MetadataWorkspace workspace = objContext.MetadataWorkspace; EdmItemCollection cCollection = workspace.GetItemCollection(DataSpace.CSpace) as EdmItemCollection; StorageMappingItemCollection csCollection = new StorageMappingItemCollection(cCollection, sCollection, mReaders); workspace.RegisterItemCollection(sCollection); workspace.RegisterItemCollection(csCollection); EntityContainer container = workspace.GetItem("WSJDEModelStoreContainer", DataSpace.SSpace); foreach (EntitySetBase entitySetBase in container.BaseEntitySets) { string schema = entitySetBase.Schema; if (schema != null) { string name = schema.Substring(schema.Length - 3); if (name == "CTL") { switch (environment) { case "Dev": typeof (EntitySetBase).GetField("_schema", BindingFlags.NonPublic | BindingFlags.Instance) .SetValue(entitySetBase, devCTL); break; case "QA": typeof (EntitySetBase).GetField("_schema", BindingFlags.NonPublic | BindingFlags.Instance) .SetValue(entitySetBase, qaCTL); break; case "Prod": typeof (EntitySetBase).GetField("_schema", BindingFlags.NonPublic | BindingFlags.Instance) .SetValue(entitySetBase, prodCTL); break; } } if (name == "DTA") { switch (environment) { case "Dev": typeof (EntitySetBase).GetField("_schema", BindingFlags.NonPublic | BindingFlags.Instance) .SetValue(entitySetBase, devDTA); break; case "QA": typeof (EntitySetBase).GetField("_schema", BindingFlags.NonPublic | BindingFlags.Instance) .SetValue(entitySetBase, qaDTA); break; case "Prod": typeof (EntitySetBase).GetField("_schema", BindingFlags.NonPublic | BindingFlags.Instance) .SetValue(entitySetBase, prodDTA); break; } } } } } } }