2011-06-28 36 views
18

一般情況下,我更傾向於使用下面的駱駝情況約定來命名我的SQL數據庫列:實體框架 - 善用第一屬性名稱字母

駝峯(注意,第一個字母是小寫)。

但隨着C#中工作時,我喜歡在以下約定來命名我的對象的公共屬性:

駝峯(注意,首先是在uppwer情況下)。

實體框架的默認行爲是將創建的類的屬性命名爲與它們在數據庫中的相對列名相匹配。

項目/解決方案級別中是否有任何屬性可以更改以解決此問題?

+0

它dbFirst接近ryt嗎? –

+0

我已經嘗試重命名ADO.NET實體數據模型設計器(雙擊.edmx文件)上的表,但如果我在那裏重命名錶,那麼這些方法也會得到重命名。例如,如果我將表'customer'重命名爲'Customer',那麼方法'AddTocustomers'get就會重命名爲'AddToCustomers1',爲什麼visual studio會放置1? –

+0

你只需要修改屬性名稱ryt? –

回答

3

我不知道一個解決方案級別的,但你可以在你的實體的屬性集,

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

謝謝,雖然我正在尋找一些會影響整個模型的東西,因爲對於每個類都要經歷整套屬性是一件麻煩事。 –

0

可以在.edmx文件更改。只需單擊屬性名稱並將其重命名爲camel case,並且每當您嘗試使用該對象訪問它時都會反映相同的情況。

+3

謝謝,儘管我正在尋找會影響整個模型的東西,因爲對於每個類都要經歷整套屬性是一件麻煩事。 –

2

實現這並非不可能,但這並不容易。其中一些取決於你正在使用哪種類型的ef模型,無論是先編碼還是先數據庫/模型(在這方面它們是相似的),或者如果你使用的是舊的基於ObjectContext的方法。通常,EF使用T4模板創建除代碼之外的所有實際類和模型,因此可以編輯T4模板並生成任何您想要的內容,例如使用PascalCasing自動生成屬性。

如果您先使用代碼(其實並不需要先編寫代碼,那是一個糟糕的名字),那麼您可以使用Entity Framework電源工具對數據庫進行逆向工程,以便對第一個模型進行逆向工程,用T4來做到這一點。

如果您先使用實際代碼(即您創建模型並從模型生成數據庫),那麼在現有EF5或更低版本中可能無法實現。 EF6(目前在alpha中)有一些被稱爲自定義約定的東西,您可能可以用它來做這件事,但離生產質量還有很長的路要走。

0

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

隨着inbuild EDMX desinger這個心不是可能的,因爲常規的犯規的「從數據庫更新」有這樣的功能。

0

該類代碼是從T4模板生成的。根據您的配置,這可能已經存在於您的項目中,或者EDMX可能正在使用內置的EDMX,在這種情況下,您需要添加自己的配置,並在EDMX中將「代碼生成策略」設置爲「無」屬性(通過模型瀏覽器)。從這個文件中很容易找到並修改類和屬性名稱的生成。

默認是調用一個函數Escape,這是在定義包括文件「IDE /擴展/微軟/實體框架工具/模板/包括」 Visual Studio的文件夾下,最終只是調用CreateEscapedIdentifier。只需用字符串的大寫版本調用它即可。

FYI:這些名字從從數據庫中EDMX定義,而不是直接在EntityTypeNavigationProperty對象來。如果您正在使用EDMX的「從數據庫生成」功能,名稱可能已經過一次轉換,原始表名不會保留在模型中。不過,這可能不會成爲問題。

1

此前我也有過這樣的問題。因此,我只需在c#中編寫一個工具來重命名現有的edmx文件,然後在重命名edmx文件的每個部分之後,使用T4模板重新生成Poco類。它解決了我的問題。它使用Camel Case屬性生成預期的POCO類。基本上在edmx我們有3層。所以我們需要修改它們的兩層。

  • MappingsSection
  • ConceptualModelsSection

請找到下面的類來做到這一點。

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再次,您可能需要再次運行此工具。

1

有辦法做到這一點,一些被別人已經指出..

我發現一個類,這是否......

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做那件事你可以實現

另一個是

去解=>並找到文件夾OBJ /調試/ 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> 
0

那麼你可以編輯在實際上EDMX的名字,但每次從數據庫又回到了做一遍刷新。

使用edmx類型數據類型時唯一可行的方法是在數據庫的表中使用正確的名稱(使用大寫字母),否則將會很乏味。

你可以使用鏈接到sql來代替,在這種情況下,你可以定義你的數據類,並提供一個名稱屬性。但是要警告,這種方法明顯更加手動,並且在大多數地方被中止,因爲它需要更多的思考來設置edmx autogeneration,這是一種點擊,點擊,下一種方法。

所以是的,你可以在edmx中編輯名字,但是考慮放棄你的camelCasing,而不是在edmx的hommage中,這樣可以節省大量的工作時間,或者你的.net自動生成的代理類看起來很奇怪,如你所知。

12

是的。這裏可以看到完整的示例:

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」。

+0

我使用EF Core 2.0.0,它似乎'modelBuilder.Properties()'不存在。 EF Core還有其他解決方案嗎? – Poulad

+0

我在這裏找到了我的答案:https://github.com/aspnet/EntityFrameworkCore/issues/5159#issuecomment-256300665 – Poulad