简体   繁体   English

实体框架 - 大写第一个属性名称字母

[英]Entity Framework - Capitalizing first property name letter

In general, I tend to name my sql database columns using the following camel case convention:通常,我倾向于使用以下驼峰式命名约定命名我的 sql 数据库列:

camelCase (notice that the first letter is in lower case). camelCase(注意第一个字母是小写的)。

But when working with C#, I like to name my object's public properties in the following convention:但是在使用 C# 时,我喜欢按照以下约定命名对象的公共属性:

CamelCase (notice the first is in uppwer case). CamelCase(注意第一个是大写的)。

Entity Framework's default behaviour is to name the created classes' properties to match their relative column names as they are in the database. Entity Framework 的默认行为是命名创建的类的属性以匹配它们在数据库中的相对列名。

Is there any property in the project/solution level which can be changed in order to solve this issue?项目/解决方案级别中是否有任何属性可以更改以解决此问题?

Yes there is.就在这里。 Here you can see the full example:在这里你可以看到完整的例子:

using System;
using System.Data.Entity;

namespace ConsoleApplication1
{
    class MyDbContext : DbContext
    {
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Properties().Configure(c =>
            {
                var name = c.ClrPropertyInfo.Name;
                var newName = char.ToLower(name[0]) + name.Substring(1);
                c.HasColumnName(newName);
            });
        }

        public MyDbCondenxt(string cs) : base(cs)
        {

        }

        public DbSet<MyModel> MyModels { get; set; }

    }

    class Program
    {
        static void Main(string[] args)
        {
            var context = new MyDbContext ("DefaultConnection");
            context.MyModels.Add(new MyModel{SomeText = "hello"});
            context.SaveChanges();

            Console.ReadLine();
        }
    }

    class MyModel
    {
        public int Id { get; set; }
        public string SomeText { get; set; }
    }


}

The property name is "SomeText" and the column name is "someText".属性名称为“SomeText”,列名称为“someText”。

I dont know of a solution level but you can set an attribute on your entity我不知道解决方案级别,但您可以在实体上设置属性

[Table("myEntity")]
public class MyEntity{}

Achieving this is not impossible, but it's not going to be easy.实现这一目标并非不可能,但也绝非易事。 Some of it depends which type of ef model you're working with, either code first or database/model first (they are similar in this regard), or if you're using the old ObjectContext based methods.其中一些取决于您正在使用哪种类型的 ef model,无论是代码优先还是数据库/模型优先(在这方面它们是相似的),或者您是否使用旧的基于 ObjectContext 的方法。

In general, EF uses T4 templating to create the actual classes and models in all but code first, so it's possible to edit the T4 templates and generate whatever you want, such as automatically generating properties with PascalCasing.通常,EF 使用 T4 模板在除代码之外的所有内容中创建实际的类和模型,因此可以编辑 T4 模板并生成您想要的任何内容,例如使用 PascalCasing 自动生成属性。

If you're using Code first (which doesn't really require that you code first, it's a terrible name) then you can use the Entity Framework power tools to reverse engineer your database to code first models, and again it uses T4 to do this.如果您首先使用代码(实际上并不要求您首先编写代码,这是一个糟糕的名称),那么您可以使用 Entity Framework 电动工具对您的数据库进行逆向工程以编写第一个模型,然后它再次使用 T4 来做这个。

If you're using actual code first (ie you create your models and generate your database from the model), then it may not be possible in the existing EF5 or lower.如果您首先使用实际代码(即您创建模型并从模型生成数据库),那么在现有的 EF5 或更低版本中可能无法实现。 EF6 (currently in alpha) has something known as custom conventions that you could probably use for this, but it's still a long way from production quality. EF6(目前处于 alpha 版本)有一些称为自定义约定的东西,您可能会使用它,但它距离生产质量还有很长的路要走。

Earlier I also had that kind of problem.之前我也遇到过这样的问题。 So I simply write a tool in c# to rename the existing edmx file and then after the renaming each section of edmx file,Next using T4 template regenerate the Poco classes.所以我简单地在c#中写了一个工具来重命名现有的edmx文件,然后在重命名edmx文件的每个部分之后,接下来使用T4模板重新生成Poco类。 It resolved my problem.它解决了我的问题。 It generates the expected POCO classes with Camel Case properties.它生成具有 Camel Case 属性的预期 POCO 类。 Basically in the edmx we have 3 layers.基本上在 edmx 中我们有 3 层。 So we need to modify 2 layers of them.所以我们需要修改其中的2层。

  • MappingsSection映射部分
  • ConceptualModelsSection概念模型部分

Please find the following class to do that.请找到以下 class 来执行此操作。

namespace Edmx_Manager_V1._0
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Xml;

    public static class RenameManager
    {
        public static XmlDocument Document = new XmlDocument();
        public static string FilePath;
        public static XmlNamespaceManager nsmgr;

        /// <summary>
        /// Updates the conceptual models section.
        /// </summary>
        public static void UpdateConceptualModelsSection()
        {

            ///////////////////////update ConceptualModels section//////////////////////////////////////////////////////////

            XmlNodeList Schema = Document.SelectNodes("/edmx:Edmx/edmx:Runtime/edmx:ConceptualModels/edm:Schema", nsmgr);

            XmlNode SchemaNode = Schema[0];
            XmlElement SchemaNodeXmlElement = SchemaNode as XmlElement;

            //get all EntitySet nodes under  EntityContainer node
            XmlNodeList EntitySetlist = SchemaNodeXmlElement.GetElementsByTagName("EntitySet");

            //get all EntityType nodes under  SchemaNode
            XmlNodeList EntityTypelist = SchemaNodeXmlElement.GetElementsByTagName("EntityType");

            foreach (XmlNode EntityTypenode in EntityTypelist)
            {

                //to call GetElementsByTagName we need XmlElement object
                XmlElement EntityTypenodeelement = EntityTypenode as XmlElement;

                //get all PropertyRef nodes under  EntityType node
                XmlNodeList PropertyReflist = EntityTypenodeelement.GetElementsByTagName("PropertyRef");

                foreach (XmlNode PropertyRefnode in PropertyReflist)
                {
                    //update name attribute of Key/PropertyRef nodes
                    XmlAttribute PropertyRef_nameAttribute = PropertyRefnode.Attributes["Name"];
                    PropertyRef_nameAttribute.Value = UppercaseFirst(PropertyRef_nameAttribute.Value);
                }

                //get all Property nodes under  EntityType node
                XmlNodeList Propertylist = EntityTypenodeelement.GetElementsByTagName("Property");

                foreach (XmlNode Propertynode in Propertylist)
                {
                    //update name attribute of PropertyRef nodes
                    XmlAttribute Property_nameAttribute = Propertynode.Attributes["Name"];
                    Property_nameAttribute.Value = UppercaseFirst(Property_nameAttribute.Value);
                }

                //get all NavigationProperty nodes under  EntityType node
                XmlNodeList NavigationPropertylist = EntityTypenodeelement.GetElementsByTagName("NavigationProperty");

                foreach (XmlNode NavigationPropertynode in NavigationPropertylist)
                {
                    //update name attribute of NavigationProperty nodes
                    XmlAttribute NavigationPropertynode_nameAttribute = NavigationPropertynode.Attributes["Name"];
                    NavigationPropertynode_nameAttribute.Value = UppercaseFirst(NavigationPropertynode_nameAttribute.Value) + "s";// we append "s" for nav properties
                }
            }

            //get  Association node under  Schema node
            XmlNodeList Associationlist = SchemaNodeXmlElement.GetElementsByTagName("Association");

            //get all Association nodes and process
            foreach (XmlNode AssociationNode in Associationlist)
            {
                if (AssociationNode != null)
                {
                    XmlElement AssociationNodeXmlElement = AssociationNode as XmlElement;
                    //get all end nodes under Association
                    XmlNodeList EndNodelist2 = AssociationNodeXmlElement.GetElementsByTagName("End");

                    //get all PropertyRef nodes under Association
                    XmlNodeList PropertyReflist2 = AssociationNodeXmlElement.GetElementsByTagName("PropertyRef");

                    foreach (XmlNode PropertyRefNode2 in PropertyReflist2)
                    {
                        //update Type attribute
                        XmlAttribute PropertyRefNode2Attribute = PropertyRefNode2.Attributes["Name"];
                        PropertyRefNode2Attribute.Value = UppercaseFirst(PropertyRefNode2Attribute.Value);
                    }
                }
            }

            Console.WriteLine("ConceptualModelSection updated..");
        }

        /// <summary>
        /// Updates the mappings section.
        /// </summary>
        public static void UpdateMappingsSection()
        {

            ///////////////////////update edmx:Mappings section//////////////////////////////////////////////////////////

            XmlNodeList EntityContainerMapping = Document.SelectNodes("/edmx:Edmx/edmx:Runtime/edmx:Mappings/cs:Mapping", nsmgr);
            XmlNode EntityContainerMapping_Node = EntityContainerMapping[0];
            XmlElement EntityContainerMappingNode_XmlElement = EntityContainerMapping_Node as XmlElement;

            // update name attribute of all EntitySetMapping nodes

            //get all EntitySetMapping nodes
            XmlNodeList EntitySetMappinglist = EntityContainerMappingNode_XmlElement.GetElementsByTagName("EntitySetMapping");

            //get all EntityTypeMapping nodes
            XmlNodeList EntityTypeMappinglist = EntityContainerMappingNode_XmlElement.GetElementsByTagName("EntityTypeMapping");

            //get all ScalarProperty nodes
            XmlNodeList ScalarPropertyist = EntityContainerMappingNode_XmlElement.GetElementsByTagName("ScalarProperty");

            foreach (XmlNode ScalarPropertyNode in ScalarPropertyist)
            {
                XmlAttribute nameAttribute = ScalarPropertyNode.Attributes["Name"];
                nameAttribute.Value = UppercaseFirst(nameAttribute.Value);
            }

            Console.WriteLine("MappingSection updated..");
        }

        /// <summary>
        /// Uppercases the first.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        private static string UppercaseFirst(string name)
        {

            return char.ToUpper(name[0]) + name.Substring(1);

        }
    }
}

Usage:用法:

            RenameManager.FilePath = @"C:\Users\therath\testApp\Model1.edmx";
            // Path of edmx file in the your solution
            RenameManager.Document.Load(@RenameManager.FilePath);
            RenameManager.nsmgr = new XmlNamespaceManager(RenameManager.Document.NameTable);
            RenameManager.nsmgr.AddNamespace("edmx", "http://schemas.microsoft.com/ado/2008/10/edmx");
            RenameManager.nsmgr.AddNamespace("edm", "http://schemas.microsoft.com/ado/2008/09/edm");
            //nsmgr.AddNamespace("ssdl", "http://schemas.microsoft.com/ado/2009/02/edm/ssdl");
            RenameManager.nsmgr.AddNamespace("cs", "http://schemas.microsoft.com/ado/2008/09/mapping/cs");

            try
            {
                RenameManager.UpdateConceptualModelsSection();
                RenameManager.UpdateMappingsSection();
                RenameManager.Document.Save(@RenameManager.FilePath);
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());
            }

If you generate the edmx again you may need to run this tool again.如果您再次生成 edmx,您可能需要再次运行此工具。

there are ways to do that, some of are already pointed out by others..有办法做到这一点,其中一些已经被其他人指出..

i found one class which does that...我发现了一个 class 可以做到这一点......

namespace System.Data.Entity.ModelConfiguration.Conventions
{
  /// <summary>
 /// Convention to convert any data types that were explicitly specified, via data     annotations or <see cref="T:System.Data.Entity.DbModelBuilder"/> API,
 ///                 to be lower case. The default SqlClient provider is case   sensitive and requires data types to be lower case. This convention 
///                 allows the <see   cref="T:System.ComponentModel.DataAnnotations.ColumnAttrbiute"/> and <see cref="T:System.Data.Entity.DbModelBuilder"/> API to be case insensitive.
/// 
/// </summary>
public sealed class ColumnTypeCasingConvention : IDbConvention<DbTableColumnMetadata>,   IConvention
{
  internal ColumnTypeCasingConvention()
{
}

[SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase")]
void IDbConvention<DbTableColumnMetadata>.Apply(DbTableColumnMetadata tableColumn, DbDatabaseMetadata database)
{
  if (string.IsNullOrWhiteSpace(tableColumn.TypeName))
    return;
  tableColumn.TypeName = tableColumn.TypeName.ToLowerInvariant();
}

} } } }

explicit implementation of idbconvertion does that thing which you can implement idbconvertion 的显式实现做了你可以实现的事情

another one is to另一个是

go to solution => and find folder obj/debug/edmxresourcestoembed go 到解决方案 => 并找到文件夹 obj/debug/edmxresourcestoembed

there are three files db.csdl, db.msl, db.ssdl edit msl file => you 'll see mapping for each table like as under.有三个文件 db.csdl、db.msl、db.ssdl 编辑 msl 文件 => 您将看到每个表的映射,如下所示。

 <EntitySetMapping Name="Address">
  <EntityTypeMapping TypeName="IsTypeOf(AdventureWorksLTModel.Address)">
    <MappingFragment StoreEntitySet="Address">
      <ScalarProperty Name="AddressID" ColumnName="AddressID" />
      <ScalarProperty Name="AddressLine1" ColumnName="AddressLine1" />
      <ScalarProperty Name="AddressLine2" ColumnName="AddressLine2" />
      <ScalarProperty Name="City" ColumnName="City" />
      <ScalarProperty Name="StateProvince" ColumnName="StateProvince" />
      <ScalarProperty Name="CountryRegion" ColumnName="CountryRegion" />
      <ScalarProperty Name="PostalCode" ColumnName="PostalCode" />
      <ScalarProperty Name="rowguid" ColumnName="rowguid" />
      <ScalarProperty Name="ModifiedDate" ColumnName="ModifiedDate" />
    </MappingFragment>
  </EntityTypeMapping>
</EntitySetMapping>

You can use external tools like http://www.devart.com/entitydeveloper/您可以使用外部工具,例如http://www.devart.com/entitydeveloper/

With the inbuild EDMX desinger this isnt possible, since the "update from database" routine doesnt have such a function.使用内置 EDMX 设计器这是不可能的,因为“从数据库更新”例程没有这样的 function。

The class code is generated from a T4 template. class 代码是从 T4 模板生成的。 Depending on your configuration, this may already be in your project, or the EDMX may be using a built-in one, in which case you would need to add your own and set the "code generation strategy" to "None" in the EDMX properties (through the model browser).根据您的配置,这可能已经在您的项目中,或者 EDMX 可能正在使用内置的,在这种情况下,您需要添加自己的并在 EDMX 中将“代码生成策略”设置为“无”属性(通过 model 浏览器)。 From this file it is fairly easy to find and modify the class and property name generation.从这个文件中很容易找到并修改 class 和属性名称生成。

The default is calling an Escape function, which is defined in include files at "IDE/Extensions/Microsoft/Entity Framework Tools/Templates/Includes" under the Visual Studio folder, and ultimately just calls CreateEscapedIdentifier .默认调用一个Escape function,它在 Visual Studio 文件夹下“IDE/Extensions/Microsoft/Entity Framework Tools/Templates/Includes”的包含文件中定义,最终只调用CreateEscapedIdentifier Simply call this with the capitalized version of the string.只需使用字符串的大写版本调用它。

FYI: These names are coming from the EntityType and NavigationProperty objects as defined in the EDMX, not directly from the database.仅供参考:这些名称来自 EDMX 中定义的EntityTypeNavigationProperty对象,而不是直接来自数据库。 If you are using the "generate from database" feature for the EDMX, the names may have already gone through a transformation and the original table names are not retained in the model.如果您为 EDMX 使用“从数据库生成”功能,则名称可能已经经过转换,并且原始表名称不会保留在 model 中。 This probably won't be an issue, though.不过,这可能不会成为问题。

Well you can edit the names in the edmx actually, but everytime you refresh from database it's back to doing it again.好吧,您实际上可以在 edmx 中编辑名称,但是每次您从数据库刷新时,它都会再次执行此操作。

The only viable approach when using edmx type datatypes is to have the correct names (with capital letters) in the tables of the database or it will be to tedious.使用 edmx 类型数据类型时唯一可行的方法是在数据库表中使用正确的名称(大写字母),否则会很乏味。

You can of cause use link to sql instead, in which case you define your data classes and just supply a name property.您当然可以使用指向 sql 的链接,在这种情况下,您可以定义数据类并仅提供名称属性。 But be warned this approach is significantly more manual and is being aborted most places because it requires much more thinking to set up that edmx autogeneration which is a click, click, next approach.但请注意,这种方法明显更加手动,并且在大多数地方都被中止,因为它需要更多的思考来设置 edmx 自动生成,这是一种点击、点击、下一个方法。

So yes you can edit the names in the edmx, but consider abandoning your camelCasing for tables instead, in hommage to edmx which saves you for a ton on work in return, or your .net autogenerated proxy classes will look wierd, as you know.所以是的,您可以编辑 edmx 中的名称,但考虑放弃您的 camelCasing 来代替表格,以向 edmx 致敬,这可以为您节省大量工作作为回报,或者您的 .net 自动生成的代理类看起来很奇怪,如您所知。

You can change it in the.edmx file.您可以在 .edmx 文件中更改它。 Just click on the property name and rename it to camel case and the same will be reflected whenever you try to access it using the object.只需单击属性名称并将其重命名为驼峰式大小写,每当您尝试使用 object 访问它时都会反映相同的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM