Skip to content

Releases: sjh37/EntityFramework-Reverse-POCO-Code-First-Generator

v3.13.0

27 Mar 20:53

Choose a tag to compare

This release includes many new features and bug fixes. Please update your Database.tt file with the latest version.


New Features

#690 EF Core Owned Entities (Column Grouping)

Columns with a common prefix can now be automatically grouped into an EF Core owned entity. The generator hides the individual prefixed columns from the POCO, adds a single typed navigation property instead, emits builder.OwnsOne(...) in the configuration class, and auto-generates the owned entity POCO class.

Use the new Settings.AddOwnedEntityMappings delegate:

Settings.AddOwnedEntityMappings = delegate (List<OwnedEntityMapping> ownedEntityMappings)
{
    // Map BillingAddress_Street, BillingAddress_City, etc. on Customer → Address owned entity
    ownedEntityMappings.Add(new OwnedEntityMapping
    {
        Schema       = Settings.DefaultSchema,
        Table        = "Customer",
        ColumnPrefix = "BillingAddress_",
        PropertyName = "BillingAddress",  // property name on Customer POCO
        PropertyType = "Address",         // C# type — POCO class auto-generated
    });

    // Multiple owned entities of the same type on the same table
    ownedEntityMappings.Add(new OwnedEntityMapping
    {
        Schema       = Settings.DefaultSchema,
        Table        = "Customer",
        ColumnPrefix = "ShippingAddress_",
        PropertyName = "ShippingAddress",
        PropertyType = "Address",
    });
};

The generator produces:

// Customer.cs
public Address BillingAddress { get; set; }
public Address ShippingAddress { get; set; }

// Address.cs (auto-generated owned entity POCO)
public string Street { get; set; }
public string City { get; set; }
...

// CustomerConfiguration.cs
builder.OwnsOne(x => x.BillingAddress, y =>
{
    y.Property(x => x.Street).HasColumnName("BillingAddress_Street")...;
    ...
});

Use Settings.OwnedEntityFolder to place the auto-generated owned entity POCOs in a separate sub-folder from your regular POCOs.


#854 Nullable Reverse Navigation Properties

A new setting controls whether reverse navigation properties for optional (one-to-one) relationships are generated as nullable reference types:

Settings.NullableReverseNavigationProperties = true;

When true (and AllowNullStrings = true), reverse navigation properties are emitted as MyEntity? NavigationProperty rather than MyEntity NavigationProperty. This correctly models the fact that the parent entity can exist without the child.

Note: This setting is automatically disabled for EF6 targets, as nullable reference types require C# 8 / language version 8+.


#663 [Comment] Attribute and .HasComment() Fluent Configuration

Database column and table descriptions (SQL Server extended properties, PostgreSQL COMMENT ON) are now surfaced in generated code. EF Core only.

  • [Comment("...")] data annotation added to entity classes and properties (requires Settings.UseDataAnnotations = true)
  • .HasComment("...") added to the fluent configuration for tables and columns
[Comment("The customer's primary email address")]
public string Email { get; set; }

#608 [Description] Attribute on Enum Values

When generating enumerations from database tables, enum values can now be decorated with [Description("...")] using the column's extended property description. Enable with:

Settings.AddDescriptionAttributeToEnums = true; // in the enum table settings

This makes it straightforward to display human-readable enum descriptions at runtime via reflection.


#877 More Data Annotations

When Settings.UseDataAnnotations = true, additional data annotations are now generated:

Scenario Attribute generated
Computed columns [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
Identity columns with no generation [DatabaseGenerated(DatabaseGeneratedOption.None)]
Decimal columns [Precision(precision, scale)]
Non-Unicode string columns [Unicode(false)]
Required columns (non-nullable, non-computed) .IsRequired() suppressed in fluent config — handled by annotation

#829 GenerateHasDefaultValueSql Flag

EF Core only. A new flag causes .HasDefaultValueSql(...) to be emitted in the entity configuration for every column that has a SQL-level default:

Settings.GenerateHasDefaultValueSql = false; // default — set to true to enable

This is useful when you need to inspect database defaults programmatically via EF's model metadata (e.g. entity.GetProperty("CreatedAt").GetDefaultValueSql()).


#800 UseFolderNameInNamespace

When generating separate files into sub-folders, you can now automatically append the folder name to the namespace:

Settings.PocoFolder              = @"Data\Entities";
Settings.PocoConfigurationFolder = @"Data\Configuration";
Settings.UseFolderNameInNamespace = true;
// → namespace MyProject.Data.Entities
// → namespace MyProject.Data.Configuration

This eliminates the need to manually keep namespaces in sync with folder structure.


#803 Filtered Index Support via .HasFilter()

Index filter expressions (partial indexes) are now read from the database and emitted in the fluent configuration:

builder.HasIndex(x => x.Email)
       .IsUnique()
       .HasFilter("[Email] IS NOT NULL");

Supported for SQL Server, PostgreSQL, and SQLite.


#721 Stored Procedures and TVFs with Spaces in Column Names

Stored procedures and table-valued functions that return result sets with spaces in column names are now fully supported. The generated return model properties use ["Column Name"] accessor syntax where necessary, and the DbContext correctly maps them.


#859 Optional Parameters in Stored Procedures

Stored procedure parameters that have default values defined in the database are now treated as optional in the generated C# method signature. Parameters with defaults are moved to the end of the parameter list and given their database default as the C# default value, allowing callers to omit them:

// Before: all parameters required
public int MyProcAsync(int id, string name, int status)

// After: parameters with DB defaults become optional
public int MyProcAsync(int id, string name = null, int status = 0)

#873 ConnectionStringActions

EF Core only. A new setting lets you append additional method calls to the database provider setup in OnConfiguring without editing the generated context:

Settings.ConnectionStringActions = ".EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null)";

This generates:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseSqlServer(connectionString + ConnectionStringActions);
}

Useful for adding retry policies, query splitting behaviour, or other provider-level options.


#807 Azure SQL Active Directory Default Authentication

The SQL Server database reader now correctly handles Authentication=Active Directory Default (and other Azure AD authentication modes) in the connection string when reverse-engineering the schema. Previously, the reader could fail to connect when using passwordless Azure AD authentication.


#609 EF Core Inheritance Workaround — Protected DbContextOptions Constructor

A protected constructor accepting the non-generic DbContextOptions is now emitted on all generated DbContext classes:

protected MyDbContext(DbContextOptions options) : base(options)
{
}

This is required when using EF Core TPH/TPT/TPC table inheritance where a derived context must call a non-generic DbContextOptions base constructor. Without it, EF Core throws a runtime error when registering the derived context.


#577 FakeDbContextInDebugOnlyMode

The Fake* unit-testing classes can now be excluded from Release builds by wrapping them in #if DEBUG:

Settings.FakeDbContextInDebugOnlyMode = false; // default — set true to wrap in #if DEBUG

Useful when you want the fake context available for development and testing but don't want it shipped in production assemblies.


#543 Stored Procedure Return Model Error Handling — Improved Defaults

The Settings.ReadStoredProcReturnObjectException delegate now stores the exception message as a comment on the generated method by default (previously it did nothing):

Settings.ReadStoredProcReturnObjectException = delegate (Exception ex, StoredProcedure sp)
{
    sp.Error = ex.Message; // ← now the default behaviour
};

If a stored procedure uses temp tables or otherwise prevents schema detection, the generated method will now contain a comment explaining why the return model is incomplete, rather than silently generating an empty return model. See the wiki page for details on how to supply the return model manually.


Bug Fixes

#876 JSON ExcludePropertyConfiguration

A new ExcludePropertyConfiguration property on JsonColumnMapping suppresses the generated builder.Property(...) fluent call for a JSON column. Use this when you are configuring the column yourself in a partial class (e.g. via OwnsMany/ToJson) to avoid the EF Core "property can only be configured once" runtime error:

jsonColumnMappings.Add(new JsonColumnMapping
{
    Schema                      = "dbo",
    Table                 ...
Read more

v3.12.0

14 Feb 16:37

Choose a tag to compare

This release contains a breaking change!

Please replace this line in your existing .tt files:

Settings.UpdateColumn = delegate(Column column, Table table, List<EnumDefinition> enumDefinitions)

with

Settings.UpdateColumn = delegate(Column column, Table table, List<EnumDefinition> enumDefinitions, List<JsonColumnMapping> jsonColumnMappings)

v3.11.0

03 Jan 18:26

Choose a tag to compare

  • #870 Added EF Core 10 support for vector and json types.
  • #855 Fix missing foreign keys when using different schemas in PostgreSQL. Thanks to Mikael Flood.
  • #864 UseMappingTables doesn't work for TemplateType.FileBasedEf6. Thanks to Simona Avornicesei.
  • #858 Enum tables PostgreSQL. Thanks to Meysam Faghfouri.
  • #562 Add DbContextOptions support for factory methods. Thanks to LarryWMSN
  • #867 Add support for partial properties. Thanks to Statler.
  • #871 NetTopologySuite is used for geography types when TemplateType.FileBasedEf6. Thanks to Simona Avornicesei.
  • Deprecate EFCore 2-6.

v3.10.0

29 Jan 15:57

Choose a tag to compare

  • Added EF Core 9 support
  • #849 Added support for ARM64 processor. Thanks to Rob.
  • Removed EF Core 7 (See support planning wiki)
  • Added support property for resultsets. Thanks to Frederic.
  • #821 Enable command timeout override. Thanks to Frederic.
    With this adjustment, it is possible to override the default commandtimeout at runtime which can be necessary for specific stored procedures.
_context.Database.CommandTimeout = 300;
return _context.spMyHeavyStoredProcedure.FirstOrDefault();
  • #820 Support resultset as property instead of a field in a stored procedure return model.
  • #621 Generate async methods (PR #797). Thanks to Erwin Bovendeur.
  • #819 Added "IsSynonym" property to Table class. Thanks to grantparker77.
  • #826 Allow table with periods. Periods in table names are replaced with an underscore.
  • #37 Merge duplicate stored procedure result sets. A new setting flag which defaults to true. This will cause the generator to inspect multiple result sets to see if they are all identical. If they are all identical, the duplicates will be removed, leaving a single model.
Settings.MergeMultipleStoredProcModelsIfAllSame = true;
  • #832 Add more data annotations.
[Table("table-name", Schema = "schema-name")]
  • #838 You can now generate multiple enums from a single table that contains a grouping field. Thanks to Ryan Plemons.
  • Inflector to correctly handle words and tables ending with: Status, To and Data.
  • Added more examples of adding base classes.
  • #834 SQLite - Support multiple foreign keys. Thanks to statler.
  • #298 Forward the cancellationToken parameter to the ToListAsync methods (PR #842). Thanks to mhartmair-cubido.
  • Enable more granular prepend schema support on a table and stored procedure level (PR #824). Thanks to dsfr-be and Frederic.
/// <summary>
/// Enables more granual control if the schema name should be prepend depending on the table
/// </summary>
public static Func<Table, bool> PrependSchemaNameForTable = (table) => {
    return true;
};

/// <summary>
/// Enables more granual control if the schema name should be prepend depending on the proc
/// </summary>
public static Func<StoredProcedure, bool> PrependSchemaNameForStoredProcedure = (prod) => {
    return true;
};
  • #822 Intercept stored procedure return model creation. Thanks to Frederic Desmyter.
// Enable interception of stored procedure return model when an exception occurs. Typically, when the stored procedure contains temp tables.
// This allows you render the proper error in comments or fix the return model by manually creating the ReturnModel using a list of DataColumns
public static Action<Exception, StoredProcedure> ReadStoredProcReturnObjectException = delegate (Exception ex, StoredProcedure sp)
{
    // Example
    /*if (!sp.ReturnModels.Any() && ex.Message.StartsWith("Invalid object name", StringComparison.OrdinalIgnoreCase))
    {
        if (sp.NameHumanCase.Equals("YourProcNameHere", StringComparison.OrdinalIgnoreCase))
        {
            sp.ReturnModels.Add(new List<DataColumn>
            {
                new DataColumn("Id", typeof(int)) { AllowDBNull = false, Unique = true },
                new DataColumn("Description", typeof(string))
            });
        }
    }*/
};

// Enable interception of stored procedure return model
public static Action<StoredProcedure> ReadStoredProcReturnObjectCompleted = delegate (StoredProcedure sp)
{
    // Example of how to add a row processed boolean column to a stored procedure's return model
    /*if (sp.ReturnModels.Any() && sp.NameHumanCase.Contains("process"))
    {
        var rm = sp.ReturnModels.First();
        rm.Add(new DataColumn("RowProcessed", typeof(bool)) { AllowDBNull = false });
    }*/
};

v3.9.0

19 Nov 21:39

Choose a tag to compare

  • #817 Added support for EFCore 8.
  • #813 Added support for remote database synonyms where tables have a trigger.
  • Deprecated EFCore 2 and 5. See Support planning for information on retirements.

v3.8.4

28 Jun 17:30

Choose a tag to compare

  • #807 Correct SQL for Azure stored procedures
  • #805 IDbContext not including System.Data namespace. Thanks to Greg Bartlett.
  • EF6 - Check for Spatial types and include System.Data.Entity.Spatial

v3.8.3

18 May 22:35

Choose a tag to compare

  • Improved support for SQLite.
  • Speeded up adding in a generator .tt settings file by not trying to immediately open a not yet defined database.

v3.8.2

08 May 16:44

Choose a tag to compare

  • #736 Better PostgreSQL types support. Thanks to uyau.
  • #568 Add support for SQLite. Thanks to Statler.
  • #741 IncludeFieldNameConstants. Thanks to MarkLFT
  • #693 Support for temporal tables. Thanks to FaizulHussain
  • #802 Use .HasTrigger() for tables with computed columns for EF Core 7. Thanks to MarkLFT
  • Add installation support for Visual Studio running on a MacOS using Parallels.

v3.8.1

19 Apr 16:13

Choose a tag to compare

  • #786 Settings.UseLazyLoading = false by default. Thanks to Neal Culiner.
  • #782 Add support for memory-optimised tables.
  • Added a file audit service. You will now see a new file generated each time you save the <database>.tt file. This audit file is used to record which files were generated and at what time. Please do not edit this file as it is used to delete files that may get filtered out during the next run. Audit files are named <database>Audit.txt.
  • #774 Optional parameters in stored procedure. Thanks to @NeilN1
  • #791 Add support for FileBasedEf6 templates. Thanks to @Techhead33
  • #793 Do not use builder.HasKey on derived types where the PK columns are hidden. Thanks to Måns Tånneryd.
  • #780 Filter sequences to just those required. Thanks to @MarkLFT

v3.8.0

06 Dec 17:16

Choose a tag to compare

  • Added support for EF Core 7. This update will now check for database triggers and identify these tables to EF Core 7. EF Core 7 will generate more efficient SQL that is faster to execute but is not compatible if a trigger is on the table. If EF 7 knows there is a trigger on the table, it will revert to using standard SQL (as generated by EF Core 6).
  • Fix for non-PascalCased foreign keys ending in _id. Thanks to Bryan Tichy.
  • Include call to .UseLazyLoadingProxies() if Settings.UseLazyLoading = true. Please install the Microsoft.EntityFrameworkCore.Proxies NuGet package.