Open Closed

Don't like updating DbContext? Use this T4 code gen template #1027


0
manifestarium created

You'll want to clean it up a bit I'm sure, but here's my working solution.

Install the "Auto T4" visual studio extension to trigger a regeneration when you build your solution, and never mess with updating your DbContext again!

<#@ template language="C#" debug="True" #> <#@ output extension="cs" #> <#@ assembly name="System" #> <#@ assembly name="System.Core" #> <#@ assembly name="System.ComponentModel.DataAnnotations" #> <#@ assembly name="System.Data" #> <#@ assembly name="$(SolutionDir)Trident.Core\bin\EntityFramework.dll" #> <#@ assembly name="Microsoft.CSharp" #> <#@ assembly name="$(SolutionDir)Trident.Core\bin\Abp.dll" #> <#@ assembly name="$(SolutionDir)Trident.Core\bin\Abp.Zero.dll" #> <#@ assembly name="$(SolutionDir)Trident.Core\bin\Trident.Core.dll" #> <#@ import namespace="System" #> <#@ import namespace="System.Collections.Generic" #> <#@ import namespace="System.ComponentModel.DataAnnotations.Schema" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Threading.Tasks" #> <#@ import namespace="Trident.Domain" #> <#

var coreAssembly = typeof(Trident.TridentCoreModule).Assembly;
var persistables = 
	coreAssembly.GetExportedTypes()
	.Where(ct =&gt; !ct.IsAbstract)
	.Where(ct => ct.GetCustomAttributes(typeof(TableAttribute), false).Any())
    .OrderBy(ct => ct.Name)
	.Select(ct => new { Type = ct, TableAttribute = (TableAttribute)ct.GetCustomAttributes(typeof(TableAttribute), false).First() })
	.ToArray();

#> using System; using System.Data.Entity; using System.Data.Entity.ModelConfiguration.Conventions; using System.Data.Common; using System.Data.Entity.Migrations.History; using System.Data.Entity.Infrastructure.Interception; using System.Data.Entity.SqlServer; using System.Data.SqlClient; using System.Diagnostics; using System.Reflection; using System.Linq; using Abp.Zero.EntityFramework; using Trident.Authorization.Roles; using Trident.MultiTenancy; using Trident.Users;

namespace Trident.EntityFramework { public partial class TridentDbContext : AbpZeroDbContext<Tenant, Role, User> {

<# var pluralizationService = new System.Data.Entity.Infrastructure.Pluralization.EnglishPluralizationService(); foreach(var p in persistables) { var propName = p.TableAttribute.Name ?? pluralizationService.Pluralize(p.Type.Name); WriteLine(" public virtual IDbSet<" + p.Type.FullName + "> " + propName + " { get; set; }"); } #>

	protected override void OnModelCreating(DbModelBuilder modelBuilder)
	{
	    base.OnModelCreating(modelBuilder);
		
		// Uncomment this if you want to use non-plural table names
	    //modelBuilder.Conventions.Remove&lt;PluralizingTableNameConvention&gt;();
		
		//modelBuilder.HasDefaultSchema(Trident.TridentConstants.SchemaName);
        //modelBuilder.ChangeAbpTablePrefix&lt;Tenant, Role, User&gt;("", Trident.TridentConstants.SchemaName);
		
    /* NOTE: 
     *   Setting "Default" to base class helps us when working migration commands on Package Manager Console.
     *   But it may cause problems when working Migrate.exe of EF. If you will apply migrations on command line, do not
     *   pass connection string name to base classes. ABP works either way.
	 *   Use the context's full namespace and name, if deploying to Azure, and make sure the connection string's name matches it.
     */
    public TridentDbContext()
        : base(typeof(TridentDbContext).FullName)
    {
	
    }

    /* NOTE:
     *   This constructor is used by ABP to pass connection string defined in TridentDataModule.PreInitialize.
     *   Notice that, actually you will not directly create an instance of TridentDbContext since ABP automatically handles it.
     */
    public TridentDbContext(string nameOrConnectionString)
        : base(nameOrConnectionString)
    {
	
    }

    //This constructor is used in tests
    public TridentDbContext(DbConnection connection)
        : base(connection, true)
    {
	
    }
}

} <# #>


1 Answer(s)
  • 0
    manifestarium created

    You can just comment out the model builder stuff that references constants in my other projects.

    This assumes you have configured your projects' build output folder to "bin" instead of "bin\debug" and "bin\release". The reason for that is you don't want it referencing a debug dll if you are building in release to deploy to Azure or something. So I recommend you change your build output paths to "bin".

    But actually it works just fine if you don't, you just need to change the paths to the DLLs at the top.