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

本文关键字:框架 第一个 属性 实体 | 更新日期: 2023-09-27 18:00:45

通常,我倾向于使用以下驼色大小写约定来命名sql数据库列:

camelCase(注意第一个字母是小写)。

但是当使用C#时,我喜欢用以下约定命名对象的公共属性:

PascalCase(请注意,第一个是在更大的情况下)。

EntityFramework的默认行为是命名创建的类的属性,以匹配它们在数据库中的相对列名。

项目/解决方案级别中是否有任何属性可以更改以解决此问题?

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

是的。在这里你可以看到完整的例子:

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

}

属性名称为"SomeText",列名称为"SomeText"。

我不知道解决方案级别,但您可以在实体上设置属性

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

实现这一目标并非不可能,但并不容易。其中一些取决于您使用的是哪种类型的ef模型,要么是代码优先,要么是数据库/模型优先(在这方面它们很相似),或者您是否使用了旧的基于ObjectContext的方法。

通常,EF使用T4模板来创建除代码外的所有类和模型,因此可以编辑T4模板并生成您想要的任何内容,例如使用PascalCasing自动生成属性。

如果你使用的是代码优先(这并不真的需要你先编码,这是一个糟糕的名字),那么你可以使用实体框架强大的工具对你的数据库进行逆向工程,使其成为代码优先的模型,它再次使用T4来实现这一点。

如果您首先使用实际的代码(即创建模型并根据模型生成数据库),那么在现有的EF5或更低版本中可能不可能。EF6(目前是alpha版本)有一些被称为自定义约定的东西,你可能会使用这些约定,但它离生产质量还有很长的路要走。

早些时候我也遇到过这种问题。因此,我只需在c#中编写一个工具来重命名现有的edmx文件,然后在重命名edmx的每个部分后,接下来使用T4模板重新生成Poco类。它解决了我的问题。它生成具有Camel Case属性的预期POCO类。基本上,在edmx中,我们有3层。所以我们需要修改其中的两层。

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

请找下面的班来做这件事。

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

用法:

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

如果您再次生成edmx,您可能需要再次运行此工具。

有一些方法可以做到这一点,其中一些已经被其他人指出。。

我找到了一个这样的班级。。。

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

}}

idbconvertion的显式实现可以实现

另一个是

转到solution=>并找到文件夹obj/debug/edmxresourcestoembed

有三个文件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>

您可以在.edmx文件中更改它。只需单击属性名称并将其重命名为驼色大小写,每当您尝试使用对象访问它时,都会反映出相同的情况。

您可以使用以下外部工具http://www.devart.com/entitydeveloper/

对于内置EDMX设计程序,这是不可能的,因为"从数据库更新"例程没有这样的功能。

类代码由T4模板生成。根据您的配置,这可能已经在您的项目中,或者EDMX可能正在使用内置策略,在这种情况下,您需要添加自己的策略,并在EDMX属性中将"代码生成策略"设置为"无"(通过模型浏览器)。从这个文件中可以很容易地找到和修改类和属性名称的生成。

默认情况下调用Escape函数,该函数在Visual Studio文件夹下"IDE/Extensions/Microsoft/Entity Framework Tools/Templates/Includes"的include文件中定义,最终只调用CreateEscapedIdentifier。只需用大写的字符串来调用它。

仅供参考:这些名称来自EDMX中定义的EntityType和NavigationProperty对象,而不是直接来自数据库。如果您使用EDMX的"从数据库生成"功能,则名称可能已经经过转换,并且原始表名称不会保留在模型中。不过,这可能不会成为问题。

实际上,您可以编辑edmx中的名称,但每次从数据库刷新时,都会重新进行。

使用edmx类型数据类型时,唯一可行的方法是在数据库的表中使用正确的名称(带大写字母),否则会很乏味。

您当然可以使用到sql的链接,在这种情况下,您可以定义数据类并只提供名称属性。但请注意,这种方法明显更为手动,在大多数地方都被放弃了,因为它需要更多的思考才能建立edmx自动生成,这是一种点击、点击、下一步的方法。

因此,是的,你可以编辑edmx中的名称,但可以考虑放弃你的camelCasing for tables,以向edmx致敬,这为你节省了大量的工作作为回报,否则你的.net自动生成的代理类会看起来更糟糕,正如你所知。