且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

当使用实体框架时,是否可以强制生成的实体类为Pascal case?

更新时间:2023-02-15 17:59:19

更新:与EF6一起使用,请参阅此页面的其他答案。



感谢 Alex的回答,我现在已经扩展这个代码可以解决这个问题的一个全面的解决方案。由于这是我最喜欢的一天,我发布在这里帮助其他人面对同样的挑战。这包括一个完整的类来操作edmx文件(这里没有任何美丽的代码),它对不同的输入字符串进行了相当详细的单元测试:



几个例子: p>

some_class> SomeClass



_some_class_> SomeClass



some_1_said > Some1Said



我还有一些额外的问题需要处理:



首先,在更改字符串到pascal的情况(由于列名称如test_string和teststring,它们都解析为TestString,否则导致冲突)。



其次,我的代码这里需要一个修改生成的对象上下文类名的输入参数。



最后,我最初没有确定如何让设计器文件更新后修改edmx,所以我已经包括确切的步骤。我建议在Visual Studio中创建一个预构建步骤,它可以节省从修改的数据库模式进行更新的一些剩余工作。



将EDMX文件更新为反映数据库更改


  1. 双击edmx文件以显示设计曲面。


  2. 右键单击设计曲面,然后选择从数据库更新模型。


  3. 选择是包括敏感信息连接字符串


  4. 取消选中在App Config中保存实体连接设置(我们已经有这些)。


  5. 选择适当的数据库。在添加屏幕中,选择表格,视图等。


  6. 将复数和外键选项保留为已选中。如果从新建创建edmx文件,则
    可以输入模型名称。


  7. 点击完成。


  8. 运行下面的代码在edmx文件上。


  9. 根据应用程序的状态,您可能会在下一步看到错误。


  10. 右键单击要更新的edmx文件,然后在Visual Studio中选择运行自定义工具。这将cuse
    将要更新的designer.cs(C#)文件。


  11. 运行构建以检查没有编译器错误。 >


  12. 运行测试以确保应用程序正常运行。


  13. 根据应用程序
    已更改的更改。


替换其中的edmx文件


  1. 删除edmx文件,使用设计器文件。


  2. 右键单击实体文件夹


  3. 从创建文件对话框中选择ADO.NET实体数据模型。将其命名为您想要的对象上下文的类名(重要信息)。
    这个值在连接字符串中被引用,所以在出现问题的时候看看你的应用配置。


  4. 在选择模型内容中,选择从数据库生成


  5. 按照上述步骤3的说明进行。

      using System; 
    使用System.IO;
    使用System.Linq;
    使用System.Text;
    使用System.Xml;
    使用System.Xml.Linq;

    命名空间EdmxStringFormatter
    {
    public class Program
    {
    static void Main(string [] args)
    {
    if (args.Length< 1)return;

    string filePath = args [0];

    string entityName = null;

    //可选不要替换下划线,哪些
    //有助于在某些数据库表上命名与类似命名的
    //列的冲突。

    bool replaceUnderscores = true;

    //允许替换对象上下文类名,这是有用的
    //其中多个数据库具有edmx文件。

    bool doEntityNameReplace = false;

    if(args.Length> 1)
    {
    entityName = args [1];
    doEntityNameReplace = true;
    }

    if(args.Length> 2)
    {
    replaceUnderscores = args [2]!=0;
    }

    if(!File.Exists(filePath))
    {
    StopWithMessage(找不到指定的文件);
    return;
    }
    if(Path.GetExtension(filePath)!=.edmx)
    {
    StopWithMessage(这只适用于EDMX文件);
    return;
    }

    //处理:

    Console.WriteLine(创建备份:+ Path.ChangeExtension(filePath,.bak));
    File.Copy(filePath,Path.ChangeExtension(filePath,.bak),true);

    Console.WriteLine(阅读目标文档...);

    XDocument xdoc = XDocument.Load(filePath);

    const string CSDLNamespace =http://schemas.microsoft.com/ado/2008/09/edm;
    const string MSLNamespace =http://schemas.microsoft.com/ado/2008/09/mapping/cs;
    const string DiagramNamespace =http://schemas.microsoft.com/ado/2008/10/edmx;

    const string CSNameSpace =http://schemas.microsoft.com/ado/2008/09/mapping/cs;

    XElement csdl = xdoc.Descendants(XName.Get(Schema,CSDLNamespace))。
    XElement msl = xdoc.Descendants(XName.Get(Mapping,MSLNamespace))。
    XElement designerDiagram = xdoc.Descendants(XName.Get(Diagram,DiagramNamespace))。

    //修改重命名所有内容,而不仅仅是表名:

    #region CSDL2

    Console.WriteLine(修改CSDL ... );
    Console.WriteLine( - 修改实体集...);

    foreach(csdl.Element中的var entitySet(XName.Get(EntityContainer,CSDLNamespace))元素(XName.Get(EntitySet,CSDLNamespace)))
    {
    entitySet.Attribute(Name)。Value = FormatString(entitySet.Attribute(Name)。Value,replaceUnderscores);
    entitySet.Attribute(EntityType)。Value = FormatString(entitySet.Attribute(EntityType)。Value,replaceUnderscores);
    }

    Console.WriteLine( - 修改关联集...);
    foreach(var associationSet in csdl.Element(XName.Get(EntityContainer,CSDLNamespace))。Elements(XName.Get(AssociationSet,CSDLNamespace)))
    {
    foreach( var end in associationSet.Elements(XName.Get(End,CSDLNamespace)))
    {
    end.Attribute(EntitySet)。Value = FormatString(end.Attribute(EntitySet)。 Value,replaceUnderscores);
    }
    }

    Console.WriteLine( - 修改实体类型...);
    foreach(csdl.Elements中的var entityType(XName.Get(EntityType,CSDLNamespace)))
    {
    entityType.Attribute(Name)。Value = FormatString(entityType.Attribute (Name)。Value,replaceUnderscores);

    foreach(varType in entityType.Elements(XName.Get(Key,CSDLNamespace)))
    {
    foreach(key.Elements中的var propertyRef(XName.Get (PropertyRef,CSDLNamespace)))
    {
    propertyRef.Attribute(Name)。Value = FormatString(propertyRef.Attribute(Name)。Value,replaceUnderscores)
    }
    }

    foreach(entityType.Elements中的var属性(XName.Get(Property,CSDLNamespace)))
    {
    属性。 Attribute(Name)。Value = FormatString(property.Attribute(Name)。Value,replaceUnderscores);
    }

    foreach(var NavigationProperty in entityType.Elements(XName.Get(NavigationProperty,CSDLNamespace)))
    {
    navigationProperty.Attribute(Name ).Value = FormatString(navigationProperty.Attribute(Name)。Value,replaceUnderscores);
    }

    }

    Console.WriteLine( - modify associations ...);
    foreach(csdl.Elements中的var association(XName.Get(Association,CSDLNamespace)))
    {
    foreach(var end in association.Elements(XName.Get(End ,CSDLNamespace)))
    {
    end.Attribute(Type)。Value = FormatString(end.Attribute(Type)。Value,replaceUnderscores)
    }
    foreach(var propref in association.Descendants(XName.Get(PropertyRef,CSDLNamespace)))
    {
    // propertyrefs包含在约束
    propref.Attribute(Name)。Value = FormatString(propref.Attribute(Name)。Value,replaceUnderscores);
    }
    }

    #endregion

    #region MSL2

    Console.WriteLine(修改MSL ... );
    Console.WriteLine( - 修改实体集映射...);

    foreach(var entitySetMapping in msl.Element(XName.Get(EntityContainerMapping,MSLNamespace))。Elements(XName.Get(EntitySetMapping,MSLNamespace)))
    {
    entitySetMapping.Attribute(Name)。Value = FormatString(entitySetMapping.Attribute(Name)。Value,replaceUnderscores);

    foreach(var entityTypeMapping in entitySetMapping.Elements(XName.Get(EntityTypeMapping,MSLNamespace)))
    {
    entityTypeMapping.Attribute(TypeName)Value = FormatString (entityTypeMapping.Attribute(TypeName)。Value,replaceUnderscores);
    foreach
    (var scalarProperty in
    (entityTypeMapping.Element(XName.Get(MappingFragment,MSLNamespace)))。元素(XName.Get(ScalarProperty,MSLNamespace))

    {
    scalarProperty.Attribute(Name)。Value = FormatString(scalarProperty.Attribute(Name)。Value,replaceUnderscores);
    }
    }
    }

    Console.WriteLine( - modify association set mappings ...);元素(XName.Get(AssociationSetMapping,MSLNamespace)))
    {
    foreach(var endProperty in associationSetMapping.Elements(XName.Get(EndProperty,MSLNamespace)))
    {
    foreach(varClasstyProperty in endProperty.Elements(XName.Get(ScalarProperty,MSLNamespace ))
    {
    scalarProperty.Attribute(Name)。Value = FormatString(scalarProperty.Attribute(Name)。Value,replaceUnderscores);
    }
    }
    }
    #endregion


    #region设计器

    Console.WriteLine(修改设计师内容...);
    foreach(designerDiagram.Elements中的var项目(XName.Get(EntityTypeShape,DiagramNamespace)))
    {
    item.Attribute(EntityType)Value = FormatString(item.Attribute (EntityType)。Value,replaceUnderscores);
    }

    #endregion

    //可选择替换实体名称,以防默认Entity不是
    //足以满足您的需求。

    if(doEntityNameReplace)
    {
    Console.WriteLine(修改实体名称refs ...);

    // CSDL
    xdoc.Descendants(XName.Get(EntityContainer,CSDLNamespace))。First()Attribute(Name)Value = entityName;

    //图
    xdoc.Descendants(XName.Get(Diagram,DiagramNamespace))。First()。Attribute(Name)。Value = entityName;

    //图
    xdoc.Descendants(XName.Get(EntityContainerMapping,CSNameSpace))。First()。Attribute(CdmEntityContainer)。Value = entityName;
    }

    Console.WriteLine(写入结果...);

    using(XmlTextWriter writer = new XmlTextWriter(filePath,Encoding.Default))
    {
    writer.Formatting = Formatting.Indented;
    xdoc.WriteTo(writer);
    }
    }

    ///< summary>
    ///将字符串格式化为pascal大小写,另外在字符串中检查一个句点
    ///(在这种情况下,它跳过该句号,表示
    ///使用
    ///< / summary>
    ///< param name =str>< / param>
    ///< param name =replaceUnderscores>< / param>
    ///< returns>< / returns>
    private static string FormatString(string str,bool replaceUnderscores = true)
    {
    char [] chars = str.ToCharArray();

    var sb = new StringBuilder();

    bool previousCharWasUpper = false;
    bool lastOperationWasToLower = false;

    int startPos = 0;

    if(str.Contains(。))
    {
    if(str.IndexOf 。)<(str.Length - 1))
    {
    startPos = str.IndexOf(。)+ 1;
    }

    sb .Append(str.Substri ng(0,startPos));
    }

    for(int i = startPos; i< chars.Length; i ++)
    {
    char character = chars [i];

    if(Char.IsLetter(character))
    {
    if(Char.IsLower(character))
    {
    bool toUpper = false;

    if(i> 0)
    {
    //查看以前的字符,看看不是一个字母

    if(!Char。 IsLetter(chars [i - 1]))
    {
    toUpper = true;
    }
    }

    if(i == 0 || toUpper)
    {
    character = Char.ToUpper(character);

    lastOperationWasToLower = false;
    }
    }
    else // IsUpper = true
    {
    if(previousCharWasUpper || lastOperationWasToLower)
    {
    character = Char.ToLower (字符);

    lastOperationWasToLower = true;
    }
    }

    previousCharWasUpper = Char.IsUpper(character);

    sb.Append(character);
    }
    else
    {
    if(Char.IsDigit(character))
    {
    sb.Append(character);

    previousCharWasUpper = false;
    lastOperationWasToLower = false;
    }
    else if(!replaceUnderscores)
    {
    if(character =='_')
    {
    sb.Append(character);
    }
    }
    }
    }

    return sb.ToString();

    }

    private static void StopWithMessage(string str)
    {
    Console.WriteLine(str);

    Console.ReadLine();

    throw new InvalidOperationException(Can not continue。);
    }
    }
    }




由Chris编辑



适应Visual Studio 2013& EF6



代码名称空间需要稍微调整才能使其与 EF6一起使用:

  const string CSDLNamespace =http://schemas.microsoft.com/ado/2009/11/edm; 
const string MSLNamespace =http://schemas.microsoft.com/ado/2009/11/mapping/cs;
const string DiagramNamespace =http://schemas.microsoft.com/ado/2009/11/edmx;

const string CSNameSpace =http://schemas.microsoft.com/ado/2009/11/mapping/cs;

加上你需要照顾designerDiagram(在我的情况下,没有找到,所以只是用FirstOrDefault()替换First()并添加简单的null检查)。


The database I'm working against has table names such as "table_name". That's fine, but I'd like to generate classes in the format "TableName" to work with in C#, Pascal style.

Is this possible?

Update: For use with EF6, see additional answer on this page.

Thanks to Alex's answer, I've now extended this code to a full working solution that solves this problem. Since it's taken me most of the day, I'm posting here to help others facing the same challenge. This includes a complete class for manipulating the edmx file (no points for pretty code here) which passes fairly verbose unit tests on varying input strings:

A few examples:

some_class > SomeClass

_some_class_ > SomeClass

some_1_said > Some1Said

I had some additional issues to deal with:

Firstly optionally not replacing underscores while still changing the string to pascal case (due to column names like "test_string" and "teststring", which both resolved to "TestString" otherwise, causing collisions).

Secondly, my code here takes an input parameter that modifies the object context class name that is generated.

Lastly, I wasn't initially sure how to get the designer file to update after modifiying the edmx, so I've included exact steps. I would recommend creating a pre build step in Visual Studio, which saves some of the remaining effort in updating from a modified database schema.

Updating an EDMX File to Reflect Database Changes

  1. Double click the edmx file to show the design surface.

  2. Right click the design surface and select "update model from database".

  3. Select "yes include sensitive information in connection string".

  4. Uncheck "save entity connection settings in App Config" (we already have these).

  5. Select the appropriate database. In Add screen select Tables, Views etc.

  6. Leave pluralise and foreign key options as checked. If creating the edmx file from fresh, you are given the option to enter a model name. You can change or leave this.

  7. Click finish.

  8. Run the code below on the edmx file.

  9. Depending on the state of the application, you may see errors here until the next step.

  10. Right click the edmx file that you are updating, and select "Run custom tool" in Visual Studio. This will cuse the designer.cs (C#) file to be updated.

  11. Run build to check there are no compiler errors.

  12. Run tests to ensure application is functioning correctly.

  13. Any application issues following this should be expected according to the application changes that have been made.

Replacing an edmx file in it's entirety.

  1. Delete the edmx file, taking the designer file with it.

  2. Right click the entities folder

  3. From the create file dialogue, select ADO.NET Entity Data Model. Name it accroding to the class name you would like for your object context(IMPORTANT). This value is referenced in the connection string, so take a look at your app config in case of issues.

  4. In choose model contents, select generate from database.

  5. Follow above instructions from step 3.

    using System;    
    using System.IO;    
    using System.Linq;    
    using System.Text;    
    using System.Xml;    
    using System.Xml.Linq;
    
    namespace EdmxStringFormatter
    {
        public class Program
        {
            static void Main(string[] args)
            {
                if (args.Length < 1) return;
    
            string filePath = args[0];
    
            string entityName = null;
    
            // Optionally do not replace underscores which 
            // helps with naming collisions with siimilarly named
            // columns on some database tables.
    
            bool replaceUnderscores = true;
    
            // Allow for the replacement of the object context class name, which is useful
            // where multiple databases have edmx files.
    
            bool doEntityNameReplace = false;
    
            if (args.Length > 1)
            {
                entityName = args[1];
                doEntityNameReplace = true;
            }
    
            if (args.Length > 2)
            {
                replaceUnderscores = args[2] != "0";
            }
    
            if (!File.Exists(filePath))
            {
                StopWithMessage("Could not find specified file.");
                return;
            }
            if (Path.GetExtension(filePath) != ".edmx")
            {
                StopWithMessage("This works only on EDMX files.");
                return;
            }
    
            // Processing:
    
            Console.WriteLine("Creating backup: " + Path.ChangeExtension(filePath, ".bak"));
            File.Copy(filePath, Path.ChangeExtension(filePath, ".bak"), true);
    
            Console.WriteLine("Reading target document...");
    
            XDocument xdoc = XDocument.Load(filePath);
    
            const string CSDLNamespace = "http://schemas.microsoft.com/ado/2008/09/edm";
            const string MSLNamespace = "http://schemas.microsoft.com/ado/2008/09/mapping/cs";
            const string DiagramNamespace = "http://schemas.microsoft.com/ado/2008/10/edmx";
    
            const string CSNameSpace = "http://schemas.microsoft.com/ado/2008/09/mapping/cs";
    
            XElement csdl = xdoc.Descendants(XName.Get("Schema", CSDLNamespace)).First();
            XElement msl = xdoc.Descendants(XName.Get("Mapping", MSLNamespace)).First();
            XElement designerDiagram = xdoc.Descendants(XName.Get("Diagram", DiagramNamespace)).First();
    
            //modifications for renaming everything, not just table names:
    
            #region CSDL2
    
            Console.WriteLine("Modifying CSDL...");
            Console.WriteLine(" - modifying entity sets...");
    
            foreach (var entitySet in csdl.Element(XName.Get("EntityContainer", CSDLNamespace)).Elements(XName.Get("EntitySet", CSDLNamespace)))
            {
                entitySet.Attribute("Name").Value = FormatString(entitySet.Attribute("Name").Value, replaceUnderscores);
                entitySet.Attribute("EntityType").Value = FormatString(entitySet.Attribute("EntityType").Value, replaceUnderscores);
            }
    
            Console.WriteLine(" - modifying association sets...");
            foreach (var associationSet in csdl.Element(XName.Get("EntityContainer", CSDLNamespace)).Elements(XName.Get("AssociationSet", CSDLNamespace)))
            {
                foreach (var end in associationSet.Elements(XName.Get("End", CSDLNamespace)))
                {
                    end.Attribute("EntitySet").Value = FormatString(end.Attribute("EntitySet").Value, replaceUnderscores);
                }
            }
    
            Console.WriteLine(" - modifying entity types...");
            foreach (var entityType in csdl.Elements(XName.Get("EntityType", CSDLNamespace)))
            {
                entityType.Attribute("Name").Value = FormatString(entityType.Attribute("Name").Value, replaceUnderscores);
    
                foreach (var key in entityType.Elements(XName.Get("Key", CSDLNamespace)))
                {
                    foreach (var propertyRef in key.Elements(XName.Get("PropertyRef", CSDLNamespace)))
                    {
                        propertyRef.Attribute("Name").Value = FormatString(propertyRef.Attribute("Name").Value, replaceUnderscores);
                    }
                }
    
                foreach (var property in entityType.Elements(XName.Get("Property", CSDLNamespace)))
                {
                    property.Attribute("Name").Value = FormatString(property.Attribute("Name").Value, replaceUnderscores);
                }
    
                foreach (var navigationProperty in entityType.Elements(XName.Get("NavigationProperty", CSDLNamespace)))
                {
                    navigationProperty.Attribute("Name").Value = FormatString(navigationProperty.Attribute("Name").Value, replaceUnderscores);
                }
    
            }
    
            Console.WriteLine(" - modifying associations...");
            foreach (var association in csdl.Elements(XName.Get("Association", CSDLNamespace)))
            {
                foreach (var end in association.Elements(XName.Get("End", CSDLNamespace)))
                {
                    end.Attribute("Type").Value = FormatString(end.Attribute("Type").Value, replaceUnderscores);
                }
                foreach (var propref in association.Descendants(XName.Get("PropertyRef", CSDLNamespace)))
                {
                    //propertyrefs are contained in constraints
                    propref.Attribute("Name").Value = FormatString(propref.Attribute("Name").Value, replaceUnderscores);
                }
            }
    
            #endregion
    
            #region MSL2
    
            Console.WriteLine("Modifying MSL...");
            Console.WriteLine(" - modifying entity set mappings...");
    
            foreach (var entitySetMapping in msl.Element(XName.Get("EntityContainerMapping", MSLNamespace)).Elements(XName.Get("EntitySetMapping", MSLNamespace)))
            {
                entitySetMapping.Attribute("Name").Value = FormatString(entitySetMapping.Attribute("Name").Value, replaceUnderscores);
    
                foreach (var entityTypeMapping in entitySetMapping.Elements(XName.Get("EntityTypeMapping", MSLNamespace)))
                {
                    entityTypeMapping.Attribute("TypeName").Value = FormatString(entityTypeMapping.Attribute("TypeName").Value, replaceUnderscores);
                    foreach
                    (var scalarProperty in
                    (entityTypeMapping.Element(XName.Get("MappingFragment", MSLNamespace))).Elements(XName.Get("ScalarProperty", MSLNamespace))
                    )
                    {
                        scalarProperty.Attribute("Name").Value = FormatString(scalarProperty.Attribute("Name").Value, replaceUnderscores);
                    }
                }
            }
    
            Console.WriteLine(" - modifying association set mappings...");
    
            foreach (var associationSetMapping in msl.Element(XName.Get("EntityContainerMapping", MSLNamespace)).Elements(XName.Get("AssociationSetMapping", MSLNamespace)))
            {
                foreach (var endProperty in associationSetMapping.Elements(XName.Get("EndProperty", MSLNamespace)))
                {
                    foreach (var scalarProperty in endProperty.Elements(XName.Get("ScalarProperty", MSLNamespace)))
                    {
                        scalarProperty.Attribute("Name").Value = FormatString(scalarProperty.Attribute("Name").Value, replaceUnderscores);
                    }
                }
            }
            #endregion
    
    
            #region Designer
    
            Console.WriteLine("Modifying designer content...");
            foreach (var item in designerDiagram.Elements(XName.Get("EntityTypeShape", DiagramNamespace)))
            {
                item.Attribute("EntityType").Value = FormatString(item.Attribute("EntityType").Value, replaceUnderscores);
            }
    
            #endregion
    
            // Optionally replace the entity name in case the default of "Entity" is not
            // sufficient for your needs.
    
            if (doEntityNameReplace)
            {
                Console.WriteLine("Modifying entity name refs...");
    
                // CSDL
                xdoc.Descendants(XName.Get("EntityContainer", CSDLNamespace)).First().Attribute("Name").Value = entityName;
    
                // Diagram 
                xdoc.Descendants(XName.Get("Diagram", DiagramNamespace)).First().Attribute("Name").Value = entityName;
    
                // Diagram 
                xdoc.Descendants(XName.Get("EntityContainerMapping", CSNameSpace)).First().Attribute("CdmEntityContainer").Value = entityName;
            }
    
            Console.WriteLine("Writing result...");
    
            using (XmlTextWriter writer = new XmlTextWriter(filePath, Encoding.Default))
            {
                writer.Formatting = Formatting.Indented;
                xdoc.WriteTo(writer);
            }
        }
    
        /// <summary>
        /// Formats the string to pascal case, additionally checking for a period
        /// in the string (in which case it skips past the period, which indicates 
        /// the use of namespace in a string.
        /// </summary>
        /// <param name="str"></param>
        /// <param name="replaceUnderscores"></param>
        /// <returns></returns>
        private static string FormatString(string str, bool replaceUnderscores = true)
        {
            char[] chars = str.ToCharArray();
    
            var sb = new StringBuilder();
    
            bool previousCharWasUpper = false;
            bool lastOperationWasToLower = false;
    
            int startPos = 0;
    
            if (str.Contains("."))
            {
                if (str.IndexOf(".") < (str.Length - 1))
                {
                    startPos = str.IndexOf(".") + 1;
                }
    
                sb.Append(str.Substring(0, startPos));
            }
    
            for (int i = startPos; i < chars.Length; i++)
            {
                char character = chars[i];
    
                if (Char.IsLetter(character))
                {
                    if (Char.IsLower(character))
                    {
                        bool toUpper = false;
    
                        if (i > 0)
                        {
                            // Look at the previous char to see if not a letter
    
                            if (!Char.IsLetter(chars[i - 1]))
                            {
                                toUpper = true;
                            }
                        }
    
                        if (i == 0 || toUpper)
                        {
                            character = Char.ToUpper(character);
    
                            lastOperationWasToLower = false;
                        }
                    }
                    else // IsUpper = true
                    {
                        if (previousCharWasUpper || lastOperationWasToLower)
                        {
                            character = Char.ToLower(character);
    
                            lastOperationWasToLower = true;
                        }
                    }
    
                    previousCharWasUpper = Char.IsUpper(character);
    
                    sb.Append(character);
                }
                else
                {
                    if (Char.IsDigit(character))
                    {
                        sb.Append(character);
    
                        previousCharWasUpper = false;
                        lastOperationWasToLower = false;
                    }
                    else if(!replaceUnderscores)
                    {
                        if(character == '_')
                        {
                            sb.Append(character);
                        }
                    }
                }
            }
    
            return sb.ToString();
    
        }
    
        private static void StopWithMessage(string str)
        {
            Console.WriteLine(str);
    
            Console.ReadLine();
    
            throw new InvalidOperationException("Cannot continue.");
        }
    }
    }
    

Edit by Chris

Adapting to Visual Studio 2013 & EF6

The code namespaces need a little tweak in order to make it work with EF6:

    const string CSDLNamespace = "http://schemas.microsoft.com/ado/2009/11/edm";
    const string MSLNamespace = "http://schemas.microsoft.com/ado/2009/11/mapping/cs";
    const string DiagramNamespace = "http://schemas.microsoft.com/ado/2009/11/edmx";

    const string CSNameSpace = "http://schemas.microsoft.com/ado/2009/11/mapping/cs";

plus you need to take care of designerDiagram(in my case, it wasn't found, so just replaced First() with FirstOrDefault() and added simple null check).