Entity Framework - Заглавная буква первого имени - PullRequest
18 голосов
/ 28 июня 2011

Как правило, я обычно называю столбцы базы данных sql в соответствии со следующим соглашением о верблюдах:

camelCase (обратите внимание, что первая буква в нижнем регистре).

Но при работе сC #, мне нравится называть открытые свойства моего объекта в следующем соглашении:

CamelCase (обратите внимание, что первый - в верхнем регистре).

По умолчанию Entity Framework именует свойства созданных классовчтобы соответствовать их относительным именам столбцов, как они есть в базе данных.

Есть ли какое-либо свойство на уровне проекта / решения, которое можно изменить, чтобы решить эту проблему?

Ответы [ 9 ]

14 голосов
/ 05 ноября 2013

Да, есть. Здесь вы можете увидеть полный пример:

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.

3 голосов
/ 28 июня 2011

Я не знаю уровня решения, но вы можете установить атрибут для вашей сущности

[Table("myEntity")]
public class MyEntity{}
2 голосов
/ 06 мая 2013

Достичь этого не невозможно, но это не будет легко.Отчасти это зависит от того, с каким типом ef-модели вы работаете, сначала с кодом, либо с базой данных / моделью (они похожи в этом отношении), или от того, используете ли вы старые методы, основанные на ObjectContext.В общем, EF использует шаблоны T4 для создания реальных классов и моделей во всем, кроме кода в первую очередь, поэтому можно редактировать шаблоны T4 и генерировать все, что вы захотите, например, автоматическую генерацию свойств с помощью PascalCasing.Сначала вы используете код (который на самом деле не требует, чтобы вы сначала кодировали, это ужасное имя), затем вы можете использовать мощные инструменты Entity Framework для реинжиниринга вашей базы данных для кодирования первых моделей, и снова для этого используется T4.

Если вы сначала используете реальный код (то есть вы создаете свои модели и генерируете базу данных из модели), то это может быть невозможно в существующем EF5 или ниже.EF6 (в настоящее время в альфа-версии) имеет нечто, известное как пользовательские соглашения, которые вы, вероятно, могли бы использовать для этого, но это все еще далеко от качества производства.

1 голос
/ 05 ноября 2013

есть способы сделать это, некоторые уже указаны другими ..

Я нашел один класс, который делает это ...

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 / debug / edmxresourcestoembed

есть три файла db.csdl, db.msl, db.ssdl edit msl file => вы увидите отображение для каждой таблицы, как показано ниже.

 <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>
1 голос
/ 01 ноября 2013

Раньше у меня тоже была такая проблема.Поэтому я просто пишу инструмент на c #, чтобы переименовать существующий файл edmx, а затем после переименования каждого раздела файла edmx, затем, используя шаблон T4, заново создать классы Poco.Это решило мою проблему.Он генерирует ожидаемые классы POCO со свойствами Camel Case.В основном в EDMX у нас есть 3 слоя.Поэтому нам нужно изменить их 2 слоя.

  • 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, возможно, вам придется снова запустить этот инструмент.

0 голосов
/ 05 ноября 2013

Ну, на самом деле вы можете редактировать имена в edmx, но каждый раз, когда вы обновляете базу данных, она возвращается к этому снова.

Единственный жизнеспособный подход при использовании типов данных типа edmx - иметь правильные имена (с заглавными буквами) в таблицах базы данных, иначе это будет утомительно.

Вместо этого вы можете использовать ссылку на sql, в этом случае вы определяете свои классы данных и просто указываете свойство name. Но имейте в виду, что этот подход является значительно более ручным и в большинстве мест прерывается, потому что для настройки автоматической генерации edmx требуется щелчок, щелчок, следующий подход.

Так что да, вы можете редактировать имена в edmx, но подумайте о том, чтобы вместо этого отказаться от использования camelCasing для таблиц, в отличие от edmx, который сэкономит вам кучу на работе взамен, или ваши автоматически сгенерированные прокси-классы .net будут выглядеть странно, так как Вы знаете.

0 голосов
/ 31 октября 2013

Код класса генерируется из шаблона T4.В зависимости от вашей конфигурации, это может уже быть в вашем проекте, или EDMX может использовать встроенную, в этом случае вам нужно будет добавить свою собственную и установить для «стратегии генерации кода» значение «Нет» в EDMX.свойства (через браузер модели).Из этого файла довольно легко найти и изменить генерацию имени класса и свойства.

По умолчанию вызывается функция Escape, которая определена во включаемых файлах в "IDE / Extensions / Microsoft/ Инструменты Entity Framework / Шаблоны / Включает " в папке Visual Studio и, в конечном счете, просто вызывает CreateEscapedIdentifier .Просто вызовите это с заглавной версией строки.

К вашему сведению: эти имена происходят из EntityType и NavigationProperty , как определено в EDMX, а не непосредственно избаза данных.Если вы используете функцию «Сгенерировать из базы данных» для EDMX, имена, возможно, уже прошли преобразование, и исходные имена таблиц не сохраняются в модели.Это, вероятно, не будет проблемой, однако.

0 голосов
/ 31 октября 2013

Вы можете использовать внешние инструменты, такие как http://www.devart.com/entitydeveloper/

С встроенной программой разработки EDMX это невозможно, поскольку подпрограмма «обновление из базы данных» не имеет такой функции.

0 голосов
/ 28 июня 2011

Вы можете изменить его в файле .edmx. Просто нажмите на имя свойства и переименуйте его в случай верблюда, и это будет отражаться всякий раз, когда вы пытаетесь получить к нему доступ с помощью объекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...