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

2024-01-21

我正在使用的数据库具有诸如“table_name”之类的表名称。很好,但我想生成“TableName”格式的类,以便在 C#、Pascal 风格中使用。

这可能吗?


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

谢谢亚历克斯的回答 https://stackoverflow.com/questions/4229812/ef4-strip-table-prefixes-on-import,我现在已将此代码扩展为解决此问题的完整工作解决方案。由于这花了我一整天的时间,我在这里发帖是为了帮助其他面临同样挑战的人。这包括一个用于操作 edmx 文件的完整类(这里没有漂亮的代码),它通过不同输入字符串的相当详细的单元测试:

举几个例子:

一些类 > 一些类

_some_class_ > 某些类

一些_1_说 > 一些1说

我还有一些其他问题需要处理:

首先,可以选择不替换下划线,同时仍将字符串更改为帕斯卡大小写(由于“test_string”和“teststring”等列名称,它们都解析为“TestString”,否则会导致冲突)。

其次,我的代码采用一个输入参数来修改生成的对象上下文类名称。

最后,我最初不确定如何在修改 edmx 后更新设计器文件,因此我包含了确切的步骤。我建议在 Visual Studio 中创建预构建步骤,这可以节省从修改后的数据库架构进行更新时剩下的一些工作。

更新 EDMX 文件以反映数据库更改

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

  2. 右键单击设计图面并选择“从数据库更新模型”。

  3. 选择“是,在连接字符串中包含敏感信息”。

  4. 取消选中“在应用程序配置中保存实体连接设置”(我们已经有这些)。

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

  6. 将复数和外键选项保留为选中状态。如果从新创建 edmx 文件,您 可以选择输入型号名称。您可以更改或保留此设置。

  7. 单击完成。

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

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

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

  11. 运行 build 检查是否有编译器错误。

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

  13. 此后出现的任何应用程序问题都应根据应用程序进行预期 已做出的更改。

完整替换 edmx 文件。

  1. 删除 edmx 文件,同时删除设计器文件。

  2. 右键单击实体文件夹

  3. 从创建文件对话框中,选择 ADO.NET 实体数据模型。根据您想要的对象上下文的类名对其进行命名(重要)。 该值在连接字符串中引用,因此请查看您的应用程序配置以防出现问题。

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

  5. 按照上述步骤 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.");
        }
    }
    }
    

克里斯编辑

适配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(在我的例子中,没有找到它,所以只需将 First() 替换为 FirstOrDefault() 并添加简单的空检查)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用实体框架时,是否可以强制生成的实体类为 Pascal 大小写? 的相关文章

随机推荐

  • Microsoft Edge 请求后退/前进按钮上的新页面

    单击后退和前进按钮时 最新版本的 Microsoft Edge 浏览器 41 162 会请求新页面 我在多个平台上测试了多个浏览器 只有 Edge 表现出这种行为 这是一个测试页 http www easynotecards com sta
  • aws sagemaker模型训练中是否有某种持久的本地存储?

    我用aws sagemaker做了一些实验 从S3下载大数据集的时间是非常有问题的 特别是当模型仍处于开发阶段 并且你想要某种相对较快的初始反馈时 是否有某种本地存储或其他方式来加快速度 EDIT我指的是批量训练服务 它允许您以 Docke
  • 为什么 Flask 会话的值必须是 JSON 可序列化的?

    我正在尝试在 Flask 应用程序中为用户会话实例化一个基本模型实例 我对我的类必须是 JSON 可序列化的要求感到措手不及 我认为会话字典只是存储会话信息的任意构造 但听起来它的使用有更多限制 其中之一显然是 JSON 可序列化的值 还有
  • 可继承的版本 Maven 插件规则

    跑步时mvn versions display dependency updates为了版本 Maven 插件 https www mojohaus org versions maven plugin 我看到很多这样的事情 INFO org
  • 角度分量的类型

    我可以将角度组件类称为类型吗 我看到 Ionic 的用途any对于组件 在 Typescript 中是否可以声明一个仅需要组件类的参数类型 我看到了这个问题 但组件在构造函数中没有任何共同点 将类作为参数传递会导致 不可更新 错误 http
  • 如何将消息从后台服务发布到 UI 片段?

    我有一个问题EventBus来自绿色机器人 我试图从我的同步适配器的后台服务发布一个事件 并将其捕获在一个片段中以更新 UI 问题是 当我尝试从同步适配器发布事件时 我在调试日志中收到以下内容 No subscribers register
  • R闪亮:如何将本地图像放入闪亮的表中

    如果图像存储在我的机器上 我似乎无法在表格中显示图像 如果图像由 URL 指定 我可以让它工作 但我不知道有什么简单的方法来 提供 图像 以便可以通过 URL 找到它 而不是仅使用图像文件名并放置文件与 ui R 和 server R 位于
  • C++ std::filesystem::filesystem_error 试图读取系统卷信息等异常

    我正在尝试解决在尝试递归遍历根驱动器中的所有文件 如 C D 等 时引发的异常 我在 Mingw64 上使用 GCC 编译器版本 9 3 0 尝试读取系统卷信息时出现 std filesystem filesystem error 示例输出
  • CSS 过渡表格行高

    我有一个 CSS 表 所有行的高度相同 但当用户单击其中一行时 所选行应占据整个表格高度 其余行应逐渐消失 我通过简单的设置就可以工作display none在所有其他行上 但我想做一些过渡 我尝试过设置max height到 100 然后
  • 如何使用boto3通过另一个帐户的SQS订阅一个帐户的SNS主题?

    我正在尝试在一个帐户中创建一个 SNS 主题并将其附加到配置规则 我有 3 个这样的帐户 并且想在每个帐户中创建 SNS 主题 现在我想通过第四个帐户的SQS订阅3个不同帐户的所有3个主题 我可以手动完成 有人可以告诉我如何通过 boto3
  • google-apps-script 更改列格式

    需要格式化列 c e 和其他一些列 以使用以下格式显示日期 2014 年 7 月 4 日 不知道该怎么做 谷歌脚本新手 要使用 Apps 脚本执行此操作 您可以使用设置数字格式 数字格式 https developers google co
  • SSL 是如何工作的?

    我知道这不是一个具体的问题 但我阅读了这个主题大约一个小时 但找不到任何有关它的基本信息 SSL 是如何工作的 什么是私钥和公钥 为什么必须在公司购买证书以及自己签署证书有什么区别 到底什么是这样的证书 我读过几个网站 维基百科信息 Sta
  • Python:减少字典的内存使用

    我正在尝试将几个文件加载到内存中 这些文件具有以下 3 种格式之一 字符串 TAB 整型 字符串 TAB 浮点数 int TAB 浮点数 事实上 它们是 ngram 静态文件 以防这有助于解决问题 例如 i love TAB 10 love
  • Angular 2 - 服务在调用方法之前消耗其他服务

    我有这样的场景 后端 json devServer http server1 proServer http server2 use devServer 全局服务 ts import Injectable from angular core
  • 在哪里可以找到 C++11 标准论文? [复制]

    这个问题在这里已经有答案了 可能的重复 在哪里可以找到当前的 C 或 C 标准文档 https stackoverflow com questions 81656 where do i find the current c or c sta
  • FFMPEG API:如何使用 av_open_input_file 连接到 RTSP 流?

    我正在尝试使用 av open input file 连接到一些 RTSP 流 如下所示 AVFormatContext ic avcodec register all av register all av open input file
  • Java 中可序列化和外部化有什么区别?

    有什么区别Serializable http java sun com javase 6 docs api java io Serializable html and Externalizable http java sun com jav
  • 冒泡排序与选择排序相比如何?

    哪种排序技术更快 冒泡排序或选择排序 为什么 两者效率相同吗 维基百科 http en wikipedia org wiki Selection sort说 强调 Among simple average case n2 algorithm
  • 如何通过拒绝selenium webdriver中的弹出窗口来关闭浏览器

    我有一个测试用例 登录后 在某个页面上 当用户尝试关闭浏览器时 它将显示弹出窗口 警报 询问 您可能会丢失数据 确定要继续吗 有两个选项 离开页面 留在页面上 单击特定选项 页面将执行操作 留在页面 不会离开页面 离开页面 将关闭浏览器 现
  • 使用实体框架时,是否可以强制生成的实体类为 Pascal 大小写?

    我正在使用的数据库具有诸如 table name 之类的表名称 很好 但我想生成 TableName 格式的类 以便在 C Pascal 风格中使用 这可能吗 更新 要与 EF6 一起使用 请参阅本页上的其他答案 谢谢亚历克斯的回答 htt