Подтвердить что ты не робот

Entity Framework - заглавная буква имени свойства

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

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

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

CamelCase (обратите внимание, что первое находится в верхнем случае).

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

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

4b9b3361

Ответ 1

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

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".

Ответ 2

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

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

Ответ 3

Достижение этого не невозможно, но это будет нелегко. Некоторые из них зависят от типа модели ef, с которой вы работаете, сначала кода или базы данных/модели (они аналогичны в этом отношении), или если вы используете старые методы на основе ObjectContext.

В общем, EF использует T4 templating для создания фактических классов и моделей во всех, кроме первого кода, поэтому можно редактировать шаблоны T4 и генерировать все, что вы хотите, например, автоматически генерировать свойства с помощью PascalCasing.

Если вы сначала используете код (который на самом деле не требует, чтобы вы сначала кодировали, это ужасное имя), вы можете использовать инструменты Power Entity Framework для обратной инженерии вашей базы данных для кодирования первых моделей, и снова она использует T4 для этого.

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

Ответ 4

Раньше у меня также была такая проблема. Поэтому я просто пишу инструмент в С#, чтобы переименовать существующий файл 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, вам может понадобиться снова запустить этот инструмент.

Ответ 5

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

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

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>

Ответ 6

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

Ответ 7

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

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

Ответ 8

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

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

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

Ответ 9

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

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

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

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