Оказывается, простое изменение шаблона T4 по умолчанию было действительно очень простым. Внутри GetTypeName
есть проверка is StructuralType
, которая обрабатывает все непримитивные типы. Это довольно хорошо фиксировало большинство моих проблем. Тогда это был вопрос Ctrl-F
для ключевых слов. Мое расстройство просто получало лучшее из меня, когда я изначально разместил этот вопрос.Использование шаблона T4 для принудительной установки PascalCase (TitleCase) для объектов в Entity Framework 6
-
я был обеспечен с базой данных, содержащей все имена таблиц и имена столбцов в snake_case. База данных не может быть изменена. Я надеюсь использовать мощь шаблонов T4 для автоматического генерации всех классов, членов, свойств, свойств навигации и т. Д. В PascalCase (TitleCase).
До сих пор я прилично закрываю, но я начинаю застревать.
namespace PokeDB
{
using System;
using System.Collections.Generic;
public partial class Ability
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public ability()
{
this.ability_changelog = new HashSet<ability_changelog>();
this.ability_flavor_text = new HashSet<ability_flavor_text>();
this.ability_names = new HashSet<ability_names>();
this.ability_prose = new HashSet<ability_prose>();
this.conquest_pokemon_abilities = new HashSet<conquest_pokemon_abilities>();
this.pokemon_abilities = new HashSet<pokemon_abilities>();
}
public long id { get; set; }
public string identifier { get; set; }
public long generation_id { get; set; }
public bool is_main_series { get; set; }
public virtual generation Generation { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<AbilityChangelog> AbilityChangelog { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<AbilityFlavorText> AbilityFlavorText { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<AbilityNames> AbilityNames { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<AbilityProse> AbilityProse { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<ConquestPokemonAbilities> ConquestPokemonAbilities { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<PokemonAbilities> PokemonAbilities { get; set; }
}
}
Как было показано выше, я получил имя класса, имена навигационных свойств, некоторые из возвращаемых значений навигационных свойств, а также имя файла. Там, где я застрял, - это имя конструктора, назначения конструктора, свойства и оставшиеся свойства свойств навигации.
Прямо сейчас, я просто заменяю все ссылки строки на CultureInfo.CurrentCulture.TextInfo.ToTitleCase(string).Replace("_", "")
.
Для примера, для имени класса:
public string EntityClassOpening(EntityType entity)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1}partial class {2}{3}",
Accessibility.ForType(entity),
_code.SpaceAfter(_code.AbstractOption(entity)),
_code.Escape(entity),
_code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType)));
}
изменено на:
public string EntityClassOpening(EntityType entity)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1}partial class {2}{3}",
Accessibility.ForType(entity),
_code.SpaceAfter(_code.AbstractOption(entity)),
CultureInfo.CurrentCulture.TextInfo.ToTitleCase(_code.Escape(entity)).Replace("_", ""),
_code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType)));
}
Это был долгий и утомительный процесс, но это лучше, чем абсолютно ничего. Я надеялся, что у вас, ребята, может быть несколько советов для меня или немного более чистого решения? Это мой первый раз, используя любой тип настраиваемого T4-шаблона. Похоже, я должен был сбить некоторые из них одним махом в некоторых методах TypeManager
. Я просто не совсем уверен, где.
Я нашел пару вопросов StackOverflow и пару сообщений в блогах об использовании шаблонов T4 для этого, но, к сожалению, шаблоны никогда не были разделены.
Даже если это не идеальное решение, я был бы признателен за любое руководство.
using System.Linq;
namespace PokeDB
{
public class ConsoleDriver
{
public static readonly PokeDBContainer PokeDB = new PokeDBContainer();
public static void Main(string[] args)
{
System.Diagnostics.Debug.WriteLine(PokeDB.Pokemon);
var x = PokeDB.Pokemon.ToList();
}
}
}
Выше текущий драйвер тест, который я написал, чтобы проверить мой DbContext. Самый первая строка завершается с следующим сообщением: An unhandled exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll Additional information: The entity type Pokemon is not part of the model for the current context.
namespace PokeDB
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
[Table("pokemon")]
public partial class Pokemon
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Pokemon()
{
this.Encounters = new HashSet<Encounter>();
this.PokemonAbilities = new HashSet<PokemonAbilities>();
this.PokemonForms = new HashSet<PokemonForms>();
this.PokemonGameIndices = new HashSet<PokemonGameIndices>();
this.PokemonItems = new HashSet<PokemonItems>();
this.PokemonMoves = new HashSet<PokemonMoves>();
this.PokemonStats = new HashSet<PokemonStats>();
this.PokemonTypes = new HashSet<PokemonTypes>();
}
public long Id { get; set; }
public string Identifier { get; set; }
public Nullable<long> SpeciesId { get; set; }
public long Height { get; set; }
public long Weight { get; set; }
public long BaseExperience { get; set; }
public long Order { get; set; }
public bool IsDefault { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Encounter> Encounters { get; set; }
public virtual PokemonSpecies PokemonSpecies { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<PokemonAbilities> PokemonAbilities { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<PokemonForms> PokemonForms { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<PokemonGameIndices> PokemonGameIndices { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<PokemonItems> PokemonItems { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<PokemonMoves> PokemonMoves { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<PokemonStats> PokemonStats { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<PokemonTypes> PokemonTypes { get; set; }
}
}
Это мой текущим Pokemon.cs файл, который был создан с помощью Т4. И это моя DbSet декларация внутри PokeDBContext.cs:
public virtual DbSet<Pokemon> Pokemon { get; set; }
Я получаю правильный Intellisense, так как классы настроены должным образом. Я просто получаю мгновение InvalidOperationException
всякий раз, когда я пытаюсь получить доступ к объектам.Обратите внимание, что истинный объект базы данных равен pokemon.
Почему бы вам не рассмотреть возможность использования EF ПОКО по этой ссылке https://marketplace.visualstudio.com/items?itemName=SimonHughes.EntityFrameworkReversePOCOGenerator – Aravind
@Aravind Этот инструмент выглядит действительно удивительный и кажется, что он должен делать именно то, что мне нужно. Однако при настройке строки подключения у меня возникают проблемы. Строка подключения, созданная мастером EF, не работает. Я все время получаю сообщение об ошибке, когда поставщик System.Data.EntityClient не загружается. Но он работает для нормальных преобразований. –
Ник. Пожалуйста, обновите сообщение с скриншотом ошибки вместе с соответствующим кодом, где возникает ошибка – Aravind