【发布时间】:2017-01-09 05:20:06
【问题描述】:
事实证明,简单地修改默认的 T4 模板实际上非常容易。在GetTypeName 内部有一个is StructuralType 检查,它处理所有非原始类型。这很好地解决了我的大部分问题。那么这只是一个Ctrl-F 关键字的问题。当我最初发布这个问题时,我的挫败感只是让我变得最好。
--
我得到了一个数据库,其中所有的表名和列名都以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; }
}
}
这是我当前通过 T4 生成的 Pokemon.cs 文件。这是我在 PokeDBContext.cs 中的 DbSet 声明:
public virtual DbSet<Pokemon> Pokemon { get; set; }
由于课程设置正确,我得到了正确的 Intellisense。每当我尝试访问实体时,我都会立即收到InvalidOperationException。请注意,真正的数据库实体是pokemon.
【问题讨论】:
-
你为什么不考虑在这个链接上使用 EF POCO marketplace.visualstudio.com/…
-
@Aravind 这个工具看起来真的很棒,而且似乎它应该完全满足我的需要。但是,在设置连接字符串时,我一直遇到问题。 EF 向导创建的连接字符串不起作用。我不断收到有关
System.Data.EntityClient提供程序无法加载的错误消息。但它适用于正常的转换。 -
尼克。请使用错误的屏幕截图以及发生错误的相应代码更新您的帖子
-
@Aravind 我用我当前的错误更新了这个问题。
标签: c# entity-framework visual-studio entity-framework-6 t4