Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Scaffold EF Core models using Handlebars templates.
specific interfaces.
- When you run the _dotnet-ef-dbcontext-scaffold_ command again, you will see your updated reflected in the generated classes.

## Handlebars Helpers
## Handlebars Helpers and Transformers

You can register Handlebars helpers in the `ScaffoldingDesignTimeServices` where setup takes place.
- Create a named tuple as shown with `myHelper` below.
Expand Down Expand Up @@ -110,3 +110,30 @@ public class ScaffoldingDesignTimeServices : IDesignTimeServices
}
```
- To use Handlebars helper defined above, add the following to any of the .hbs files within the CodeTemplates folder: `{{my-helper}}`

## Extending the OnModelCreating Method

There are times when you might like to modify generated code, for example, by adding a `HasConversion` method to an entity property in the `OnModelCreating` method of the generated class that extends `DbContext`. However, doing so may prove futile because added code would be overwritten the next time you run the `dotnet ef dbcontext scaffold` command.
- Rather than modifying generated code, a better idea would be to extend it by using _partial classes and methods_. To enable this scenario, the generated `DbContext` class is already defined using the `partial` keyword, and it contains a partial `OnModelCreatingExt` method that is invoked at the end of the `OnModelCreating` method.
- To implement the partial method, simply add a new class to your project with the same name as the generated `DbContext` class, and define it as `partial`. Then add a `OnModelCreatingExt` method with the same signature as the partial method defined in the generated `DbContext` class.

```csharp
// Place in separate class file (NorthwindSlimContextExt.cs)
public partial class NorthwindSlimContext
{
partial void OnModelCreatingExt(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>()
.Property(e => e.Country)
.HasConversion(
v => v.ToString(),
v => (Country)Enum.Parse(typeof(Country), v));

modelBuilder.Entity<Customer>()
.Property(e => e.Country)
.HasConversion(
v => v.ToString(),
v => (Country)Enum.Parse(typeof(Country), v));
}
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ namespace {{namespace}}

{{/if}}

{{{on-configuring}}}
{{{on-model-creating}}}
}
}
13 changes: 4 additions & 9 deletions sample/ScaffoldingSample/Contexts/NorthwindSlimContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,6 @@ public partial class NorthwindSlimContext : DbContext
// My Handlebars Helper
public virtual DbSet<Territory> Territory { get; set; }

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
optionsBuilder.UseSqlServer("Data Source=(localdb)\\MSSQLLocalDB; Initial Catalog=NorthwindSlim; Integrated Security=True");
}
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasAnnotation("ProductVersion", "2.2.0-rtm-35687");
Expand Down Expand Up @@ -184,6 +175,10 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
.IsRequired()
.HasMaxLength(50);
});

OnModelCreatingExt(modelBuilder);
}

partial void OnModelCreatingExt(ModelBuilder modelBuilder);
}
}
23 changes: 23 additions & 0 deletions sample/ScaffoldingSample/Contexts/NorthwindSlimContextExt.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System;
using Microsoft.EntityFrameworkCore;

namespace ScaffoldingSample.Models
{
public partial class NorthwindSlimContext
{
partial void OnModelCreatingExt(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>()
.Property(e => e.Country)
.HasConversion(
v => v.ToString(),
v => (Country)Enum.Parse(typeof(Country), v));

modelBuilder.Entity<Customer>()
.Property(e => e.Country)
.HasConversion(
v => v.ToString(),
v => (Country)Enum.Parse(typeof(Country), v));
}
}
}
8 changes: 8 additions & 0 deletions sample/ScaffoldingSample/Models/Country.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace ScaffoldingSample.Models
{
public enum Country
{
UK = 1,
USA = 2
}
}
2 changes: 1 addition & 1 deletion sample/ScaffoldingSample/Models/Customer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public Customer()
public string CompanyName { get; set; }
public string ContactName { get; set; }
public string City { get; set; }
public string Country { get; set; }
public Country Country { get; set; }

public CustomerSetting CustomerSetting { get; set; }
public ICollection<Order> Order { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion sample/ScaffoldingSample/Models/Employee.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public Employee()
public DateTime? BirthDate { get; set; }
public DateTime? HireDate { get; set; }
public string City { get; set; }
public string Country { get; set; }
public Country Country { get; set; }

public ICollection<EmployeeTerritories> EmployeeTerritories { get; set; }
}
Expand Down
52 changes: 46 additions & 6 deletions sample/ScaffoldingSample/Sample.ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,20 @@ public class ScaffoldingDesignTimeServices : IDesignTimeServices
// Add optional Handlebars helpers
services.AddHandlebarsHelpers(myHelper);

// Add optional Handlebars transformers
// Add Handlebars transformer for Country property
services.AddHandlebarsTransformers(
entityNameTransformer: n => n + "Foo",
entityFileNameTransformer: n => n + "Foo",
constructorTransformer: e => new EntityPropertyInfo(e.PropertyType + "Foo", e.PropertyName + "Foo"),
propertyTransformer: e => new EntityPropertyInfo(e.PropertyType, e.PropertyName + "Foo"),
navPropertyTransformer: e => new EntityPropertyInfo(e.PropertyType + "Foo", e.PropertyName + "Foo"));
propertyTransformer: e =>
e.PropertyName == "Country"
? new EntityPropertyInfo("Country", e.PropertyName)
: new EntityPropertyInfo(e.PropertyType, e.PropertyName));

// Add optional Handlebars transformers
//services.AddHandlebarsTransformers(
// entityNameTransformer: n => n + "Foo",
// entityFileNameTransformer: n => n + "Foo",
// constructorTransformer: e => new EntityPropertyInfo(e.PropertyType + "Foo", e.PropertyName + "Foo"),
// propertyTransformer: e => new EntityPropertyInfo(e.PropertyType, e.PropertyName + "Foo"),
// navPropertyTransformer: e => new EntityPropertyInfo(e.PropertyType + "Foo", e.PropertyName + "Foo"));
}

// Sample Handlebars helper
Expand All @@ -55,6 +62,39 @@ public class ScaffoldingDesignTimeServices : IDesignTimeServices
```
- To use Handlebars helper defined above, add the following to any of the .hbs files within the CodeTemplates folder: `{{my-helper}}`

A transformer function is added to convert the property type of the `Country` property from `string` to a `Country` `enum` that has been added to the project. More countries from the Customer table may be added.
- The commented code for `AddHandlebarsTransformers` provides an example of using all the available transformers to append `"Foo"` to the class and property names of each entity.

```csharp
public enum Country
{
UK = 1,
USA = 2
}
```

A partial `NorthwindSlimContext` class has been added to a **NorthwindSlimContextExt.cs** file with an implementation of the partial `OnModelCreatingExt` method that adds a property value conversion.

```csharp
public partial class NorthwindSlimContext
{
partial void OnModelCreatingExt(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>()
.Property(e => e.Country)
.HasConversion(
v => v.ToString(),
v => (Country)Enum.Parse(typeof(Country), v));

modelBuilder.Entity<Customer>()
.Property(e => e.Country)
.HasConversion(
v => v.ToString(),
v => (Country)Enum.Parse(typeof(Country), v));
}
}
```

## Usage

- Open a command prompt at the project root and execute:
Expand Down
7 changes: 7 additions & 0 deletions sample/ScaffoldingSample/ScaffoldingDesignTimeServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ public void ConfigureDesignTimeServices(IServiceCollection services)
// Add optional Handlebars helpers
services.AddHandlebarsHelpers(myHelper);

// Add Handlebars transformer for Country property
services.AddHandlebarsTransformers(
propertyTransformer: e =>
e.PropertyName == "Country"
? new EntityPropertyInfo("Country", e.PropertyName)
: new EntityPropertyInfo(e.PropertyType, e.PropertyName));

// Add optional Handlebars transformers
//services.AddHandlebarsTransformers(
// entityNameTransformer: n => n + "Foo",
Expand Down
5 changes: 0 additions & 5 deletions sample/ScaffoldingSample/ScaffoldingSample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.2.0" />
</ItemGroup>

<ItemGroup>
<Folder Include="Contexts\" />
<Folder Include="Models\" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\EntityFrameworkCore.Scaffolding.Handlebars\EntityFrameworkCore.Scaffolding.Handlebars.csproj" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,9 +336,14 @@ protected virtual void GenerateOnModelCreating(IModel model, bool useDataAnnotat
{
GenerateSequence(sequence, sb);
}

sb.AppendLine();
sb.AppendLine("OnModelCreatingExt(modelBuilder);");
}

sb.Append("}");
sb.AppendLine("}");
sb.AppendLine();
sb.Append("partial void OnModelCreatingExt(ModelBuilder modelBuilder);");

var onModelCreating = sb.ToString();
TemplateData.Add("on-model-creating", onModelCreating);
Expand Down
8 changes: 8 additions & 0 deletions test/Scaffolding.Handlebars.Tests/ExpectedContexts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
.WithMany(p => p.Product)
.HasForeignKey(d => d.CategoryId);
});

OnModelCreatingExt(modelBuilder);
}

partial void OnModelCreatingExt(ModelBuilder modelBuilder);
}
}
";
Expand Down Expand Up @@ -91,7 +95,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)

entity.Property(e => e.RowVersion).IsRowVersion();
});

OnModelCreatingExt(modelBuilder);
}

partial void OnModelCreatingExt(ModelBuilder modelBuilder);
}
}
";
Expand Down