实体框架-第一个属性名称字母大写
本文关键字:框架 第一个 属性 实体 | 更新日期: 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自动生成的代理类会看起来更糟糕,正如你所知。