diff --git a/README.md b/README.md
index ec83d365..1914f8bc 100644
--- a/README.md
+++ b/README.md
@@ -155,6 +155,13 @@ Entity Framework Core Generator supports generating [Read](https://efg.loresoft.
## Change Log
+### Version 6.0
+
+- upgrade to .net 8
+- add option to turn off temporal table mapping
+- add rowversion options, ByteArray|Long|ULong
+- add script template merge
+
### Version 5.0
- add support for navigation property renames
diff --git a/docs/configuration.md b/docs/configuration.md
index f544eb7b..16062729 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -102,6 +102,9 @@ data:
directory: '{Project.Directory}\Data\Mapping' # the mapping class output directory
#include XML documentation
document: false
+
+ temporal: false # if temporal table mapping is enabled. Default true
+ rowVersion: ByteArray|Long|ULong # How row versions should be mapped. Default ByteArray
# query extension class file configuration
query:
@@ -191,6 +194,7 @@ script:
namespace: '{Project.Namespace}.Domain.Context'
baseClass: ContextScriptBase
overwrite: true # overwrite existing file
+ merge: true # merge regions with existing file
# collection of script template with current Entity as a variable
entity:
- templatePath: '.\templates\entity.csx' # path to script file
@@ -199,6 +203,7 @@ script:
namespace: '{Project.Namespace}.Domain.Entity'
baseClass: EntityScriptBase
overwrite: true # overwrite existing file
+ merge: true # merge regions with existing file
# collection script template with current Model as a variable
model:
- templatePath: '.\templates\model.csx' # path to script file
@@ -207,10 +212,12 @@ script:
namespace: '{Project.Namespace}.Domain.Models'
baseClass: ModelScriptBase
overwrite: true # overwrite existing file
+ merge: true # merge regions with existing file
- templatePath: '.\templates\sample.csx' # path to script file
fileName: '{Model.Name}Sample.cs' # filename to save script output
directory: '{Project.Directory}\Domain\Models' # directory to save script output
namespace: '{Project.Namespace}.Domain.Models'
baseClass: ModelSampleBase
overwrite: true # overwrite existing file
+ merge: true # merge regions with existing file
```
diff --git a/sample/Tracker/Tracker.Core/Data/Mapping/AuditMap.cs b/sample/Tracker/Tracker.Core/Data/Mapping/AuditMap.cs
index b99bee7d..4db84ef1 100644
--- a/sample/Tracker/Tracker.Core/Data/Mapping/AuditMap.cs
+++ b/sample/Tracker/Tracker.Core/Data/Mapping/AuditMap.cs
@@ -79,6 +79,7 @@ public void Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityType
builder.Property(t => t.RowVersion)
.IsRequired()
.IsRowVersion()
+ .IsConcurrencyToken()
.HasColumnName("RowVersion")
.HasColumnType("rowversion")
.HasMaxLength(8)
diff --git a/sample/Tracker/Tracker.Core/Data/Mapping/PriorityMap.cs b/sample/Tracker/Tracker.Core/Data/Mapping/PriorityMap.cs
index 73c6e816..71e72d9b 100644
--- a/sample/Tracker/Tracker.Core/Data/Mapping/PriorityMap.cs
+++ b/sample/Tracker/Tracker.Core/Data/Mapping/PriorityMap.cs
@@ -44,13 +44,14 @@ public void Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityType
builder.Property(t => t.DisplayOrder)
.IsRequired()
.HasColumnName("DisplayOrder")
- .HasColumnType("int");
+ .HasColumnType("int")
+ .HasDefaultValue(0);
builder.Property(t => t.IsActive)
.IsRequired()
.HasColumnName("IsActive")
.HasColumnType("bit")
- .HasDefaultValueSql("((1))");
+ .HasDefaultValue(true);
builder.Property(t => t.Created)
.IsRequired()
@@ -77,6 +78,7 @@ public void Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityType
builder.Property(t => t.RowVersion)
.IsRequired()
.IsRowVersion()
+ .IsConcurrencyToken()
.HasColumnName("RowVersion")
.HasColumnType("rowversion")
.HasMaxLength(8)
diff --git a/sample/Tracker/Tracker.Core/Data/Mapping/RoleMap.cs b/sample/Tracker/Tracker.Core/Data/Mapping/RoleMap.cs
index 77fa9639..e2706008 100644
--- a/sample/Tracker/Tracker.Core/Data/Mapping/RoleMap.cs
+++ b/sample/Tracker/Tracker.Core/Data/Mapping/RoleMap.cs
@@ -65,6 +65,7 @@ public void Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityType
builder.Property(t => t.RowVersion)
.IsRequired()
.IsRowVersion()
+ .IsConcurrencyToken()
.HasColumnName("RowVersion")
.HasColumnType("rowversion")
.HasMaxLength(8)
diff --git a/sample/Tracker/Tracker.Core/Data/Mapping/StatusMap.cs b/sample/Tracker/Tracker.Core/Data/Mapping/StatusMap.cs
index b1c86342..ddb48bbf 100644
--- a/sample/Tracker/Tracker.Core/Data/Mapping/StatusMap.cs
+++ b/sample/Tracker/Tracker.Core/Data/Mapping/StatusMap.cs
@@ -44,13 +44,14 @@ public void Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityType
builder.Property(t => t.DisplayOrder)
.IsRequired()
.HasColumnName("DisplayOrder")
- .HasColumnType("int");
+ .HasColumnType("int")
+ .HasDefaultValueSql("((0))");
builder.Property(t => t.IsActive)
.IsRequired()
.HasColumnName("IsActive")
.HasColumnType("bit")
- .HasDefaultValueSql("((1))");
+ .HasDefaultValue(true);
builder.Property(t => t.Created)
.IsRequired()
@@ -77,6 +78,7 @@ public void Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityType
builder.Property(t => t.RowVersion)
.IsRequired()
.IsRowVersion()
+ .IsConcurrencyToken()
.HasColumnName("RowVersion")
.HasColumnType("rowversion")
.HasMaxLength(8)
diff --git a/sample/Tracker/Tracker.Core/Data/Mapping/TaskExtendedMap.cs b/sample/Tracker/Tracker.Core/Data/Mapping/TaskExtendedMap.cs
index cb1cfaed..82c3e0ed 100644
--- a/sample/Tracker/Tracker.Core/Data/Mapping/TaskExtendedMap.cs
+++ b/sample/Tracker/Tracker.Core/Data/Mapping/TaskExtendedMap.cs
@@ -68,6 +68,7 @@ public void Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityType
builder.Property(t => t.RowVersion)
.IsRequired()
.IsRowVersion()
+ .IsConcurrencyToken()
.HasColumnName("RowVersion")
.HasColumnType("rowversion")
.HasMaxLength(8)
diff --git a/sample/Tracker/Tracker.Core/Data/Mapping/TaskMap.cs b/sample/Tracker/Tracker.Core/Data/Mapping/TaskMap.cs
index 8a7a8b00..123a6754 100644
--- a/sample/Tracker/Tracker.Core/Data/Mapping/TaskMap.cs
+++ b/sample/Tracker/Tracker.Core/Data/Mapping/TaskMap.cs
@@ -108,6 +108,7 @@ public void Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityType
builder.Property(t => t.RowVersion)
.IsRequired()
.IsRowVersion()
+ .IsConcurrencyToken()
.HasColumnName("RowVersion")
.HasColumnType("rowversion")
.HasMaxLength(8)
diff --git a/sample/Tracker/Tracker.Core/Data/Mapping/TenantMap.cs b/sample/Tracker/Tracker.Core/Data/Mapping/TenantMap.cs
index aab2cec0..82f255dc 100644
--- a/sample/Tracker/Tracker.Core/Data/Mapping/TenantMap.cs
+++ b/sample/Tracker/Tracker.Core/Data/Mapping/TenantMap.cs
@@ -44,7 +44,7 @@ public void Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityType
.IsRequired()
.HasColumnName("IsActive")
.HasColumnType("bit")
- .HasDefaultValueSql("((1))");
+ .HasDefaultValue(true);
builder.Property(t => t.Created)
.IsRequired()
@@ -71,6 +71,7 @@ public void Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityType
builder.Property(t => t.RowVersion)
.IsRequired()
.IsRowVersion()
+ .IsConcurrencyToken()
.HasColumnName("RowVersion")
.HasColumnType("rowversion")
.HasMaxLength(8)
diff --git a/sample/Tracker/Tracker.Core/Data/Mapping/UserLoginMap.cs b/sample/Tracker/Tracker.Core/Data/Mapping/UserLoginMap.cs
index b5d3dc8b..283f9f62 100644
--- a/sample/Tracker/Tracker.Core/Data/Mapping/UserLoginMap.cs
+++ b/sample/Tracker/Tracker.Core/Data/Mapping/UserLoginMap.cs
@@ -77,7 +77,8 @@ public void Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityType
builder.Property(t => t.IsSuccessful)
.IsRequired()
.HasColumnName("IsSuccessful")
- .HasColumnType("bit");
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
builder.Property(t => t.FailureMessage)
.HasColumnName("FailureMessage")
@@ -109,6 +110,7 @@ public void Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityType
builder.Property(t => t.RowVersion)
.IsRequired()
.IsRowVersion()
+ .IsConcurrencyToken()
.HasColumnName("RowVersion")
.HasColumnType("rowversion")
.HasMaxLength(8)
diff --git a/sample/Tracker/Tracker.Core/Data/Mapping/UserMap.cs b/sample/Tracker/Tracker.Core/Data/Mapping/UserMap.cs
index 3e4bc6cc..1c9b8570 100644
--- a/sample/Tracker/Tracker.Core/Data/Mapping/UserMap.cs
+++ b/sample/Tracker/Tracker.Core/Data/Mapping/UserMap.cs
@@ -39,7 +39,8 @@ public void Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityType
builder.Property(t => t.IsEmailAddressConfirmed)
.IsRequired()
.HasColumnName("IsEmailAddressConfirmed")
- .HasColumnType("bit");
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
builder.Property(t => t.DisplayName)
.IsRequired()
@@ -62,12 +63,14 @@ public void Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityType
builder.Property(t => t.AccessFailedCount)
.IsRequired()
.HasColumnName("AccessFailedCount")
- .HasColumnType("int");
+ .HasColumnType("int")
+ .HasDefaultValueSql("((0))");
builder.Property(t => t.LockoutEnabled)
.IsRequired()
.HasColumnName("LockoutEnabled")
- .HasColumnType("bit");
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
builder.Property(t => t.LockoutEnd)
.HasColumnName("LockoutEnd")
@@ -80,7 +83,8 @@ public void Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityType
builder.Property(t => t.IsDeleted)
.IsRequired()
.HasColumnName("IsDeleted")
- .HasColumnType("bit");
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
builder.Property(t => t.Created)
.IsRequired()
@@ -107,6 +111,7 @@ public void Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityType
builder.Property(t => t.RowVersion)
.IsRequired()
.IsRowVersion()
+ .IsConcurrencyToken()
.HasColumnName("RowVersion")
.HasColumnType("rowversion")
.HasMaxLength(8)
diff --git a/sample/Tracker/Tracker.Core/Tracker.Core.csproj b/sample/Tracker/Tracker.Core/Tracker.Core.csproj
index 7abee753..fe62b2b8 100644
--- a/sample/Tracker/Tracker.Core/Tracker.Core.csproj
+++ b/sample/Tracker/Tracker.Core/Tracker.Core.csproj
@@ -8,7 +8,7 @@
-
+
diff --git a/sample/Tracker/Tracker.Scaffold/Priority.cs b/sample/Tracker/Tracker.Scaffold/Priority.cs
index 1f9c620b..3f846390 100644
--- a/sample/Tracker/Tracker.Scaffold/Priority.cs
+++ b/sample/Tracker/Tracker.Scaffold/Priority.cs
@@ -13,7 +13,7 @@ public partial class Priority
public int DisplayOrder { get; set; }
- public bool? IsActive { get; set; }
+ public bool IsActive { get; set; }
public DateTimeOffset Created { get; set; }
diff --git a/sample/Tracker/Tracker.Scaffold/Status.cs b/sample/Tracker/Tracker.Scaffold/Status.cs
index 757a7d33..9d87505a 100644
--- a/sample/Tracker/Tracker.Scaffold/Status.cs
+++ b/sample/Tracker/Tracker.Scaffold/Status.cs
@@ -13,7 +13,7 @@ public partial class Status
public int DisplayOrder { get; set; }
- public bool? IsActive { get; set; }
+ public bool IsActive { get; set; }
public DateTimeOffset Created { get; set; }
diff --git a/sample/Tracker/Tracker.Scaffold/Tenant.cs b/sample/Tracker/Tracker.Scaffold/Tenant.cs
index b761e0c6..c1d36daf 100644
--- a/sample/Tracker/Tracker.Scaffold/Tenant.cs
+++ b/sample/Tracker/Tracker.Scaffold/Tenant.cs
@@ -11,7 +11,7 @@ public partial class Tenant
public string? Description { get; set; }
- public bool? IsActive { get; set; }
+ public bool IsActive { get; set; }
public DateTimeOffset Created { get; set; }
diff --git a/sample/Tracker/Tracker.Scaffold/Tracker.Scaffold.csproj b/sample/Tracker/Tracker.Scaffold/Tracker.Scaffold.csproj
index 6758f12f..d42b6e1b 100644
--- a/sample/Tracker/Tracker.Scaffold/Tracker.Scaffold.csproj
+++ b/sample/Tracker/Tracker.Scaffold/Tracker.Scaffold.csproj
@@ -8,7 +8,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/sample/Tracker/Tracker.Scaffold/TrackerContext.cs b/sample/Tracker/Tracker.Scaffold/TrackerContext.cs
index 7d258676..99c78864 100644
--- a/sample/Tracker/Tracker.Scaffold/TrackerContext.cs
+++ b/sample/Tracker/Tracker.Scaffold/TrackerContext.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
@@ -36,7 +36,8 @@ public TrackerContext(DbContextOptions options)
public virtual DbSet UserLogins { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
- => optionsBuilder.UseSqlServer("Data Source=(local)\\sql2022;Initial Catalog=Tracker;Integrated Security=True;TrustServerCertificate=True");
+#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
+ => optionsBuilder.UseSqlServer("Data Source=(local);Initial Catalog=Tracker;Integrated Security=True;TrustServerCertificate=True");
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
@@ -64,9 +65,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
entity.Property(e => e.Created).HasDefaultValueSql("(sysutcdatetime())");
entity.Property(e => e.CreatedBy).HasMaxLength(100);
entity.Property(e => e.Description).HasMaxLength(255);
- entity.Property(e => e.IsActive)
- .IsRequired()
- .HasDefaultValueSql("((1))");
+ entity.Property(e => e.IsActive).HasDefaultValue(true);
entity.Property(e => e.Name).HasMaxLength(100);
entity.Property(e => e.RowVersion)
.IsRowVersion()
@@ -108,9 +107,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
entity.Property(e => e.Created).HasDefaultValueSql("(sysutcdatetime())");
entity.Property(e => e.CreatedBy).HasMaxLength(100);
entity.Property(e => e.Description).HasMaxLength(255);
- entity.Property(e => e.IsActive)
- .IsRequired()
- .HasDefaultValueSql("((1))");
+ entity.Property(e => e.IsActive).HasDefaultValue(true);
entity.Property(e => e.Name).HasMaxLength(100);
entity.Property(e => e.RowVersion)
.IsRowVersion()
@@ -152,8 +149,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
entity.Property(e => e.Updated).HasDefaultValueSql("(sysutcdatetime())");
entity.Property(e => e.UpdatedBy).HasMaxLength(100);
-
-
entity.HasOne(d => d.Assigned).WithMany(p => p.Tasks).HasForeignKey(d => d.AssignedId);
entity.HasOne(d => d.Priority).WithMany(p => p.Tasks).HasForeignKey(d => d.PriorityId);
@@ -196,9 +191,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
entity.Property(e => e.Id).HasDefaultValueSql("(newsequentialid())");
entity.Property(e => e.Created).HasDefaultValueSql("(sysutcdatetime())");
entity.Property(e => e.CreatedBy).HasMaxLength(100);
- entity.Property(e => e.IsActive)
- .IsRequired()
- .HasDefaultValueSql("((1))");
+ entity.Property(e => e.IsActive).HasDefaultValue(true);
entity.Property(e => e.Name).HasMaxLength(256);
entity.Property(e => e.RowVersion)
.IsRowVersion()
diff --git a/sample/Tracker/Tracker.Scaffold/scaffold.cmd b/sample/Tracker/Tracker.Scaffold/scaffold.cmd
new file mode 100644
index 00000000..b6797d58
--- /dev/null
+++ b/sample/Tracker/Tracker.Scaffold/scaffold.cmd
@@ -0,0 +1 @@
+dotnet ef dbcontext scaffold "Data Source=(local);Initial Catalog=Tracker;Integrated Security=True;TrustServerCertificate=True" Microsoft.EntityFrameworkCore.SqlServer --force
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 5642ac00..795e7eca 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -34,7 +34,7 @@
-
+
diff --git a/src/EntityFrameworkCore.Generator.Core/EntityFrameworkCore.Generator.Core.csproj b/src/EntityFrameworkCore.Generator.Core/EntityFrameworkCore.Generator.Core.csproj
index cc040c59..e3a1fc77 100644
--- a/src/EntityFrameworkCore.Generator.Core/EntityFrameworkCore.Generator.Core.csproj
+++ b/src/EntityFrameworkCore.Generator.Core/EntityFrameworkCore.Generator.Core.csproj
@@ -1,32 +1,21 @@
-
+
- net6.0;net8.0
+ net8.0
EntityFrameworkCore.Generator
1591,EF1001
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
+
diff --git a/src/EntityFrameworkCore.Generator.Core/Metadata/Generation/Property.cs b/src/EntityFrameworkCore.Generator.Core/Metadata/Generation/Property.cs
index 41613dc4..2771a1ff 100644
--- a/src/EntityFrameworkCore.Generator.Core/Metadata/Generation/Property.cs
+++ b/src/EntityFrameworkCore.Generator.Core/Metadata/Generation/Property.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Data;
using System.Diagnostics;
using Microsoft.EntityFrameworkCore.Metadata;
@@ -36,6 +36,8 @@ public class Property : ModelBase
public bool? IsRowVersion { get; set; }
+ public bool? IsConcurrencyToken { get; set; }
+
public bool? IsUnique { get; set; }
[Obsolete("Value no longer used, will be deleted")]
@@ -49,7 +51,9 @@ public class Property : ModelBase
[Obsolete("Value no longer used, will be deleted")]
public int? Scale { get; set; }
+ public object DefaultValue { get; set; }
+
public string Default { get; set; }
public ValueGenerated? ValueGenerated { get; set; }
-}
\ No newline at end of file
+}
diff --git a/src/EntityFrameworkCore.Generator.Core/ModelGenerator.cs b/src/EntityFrameworkCore.Generator.Core/ModelGenerator.cs
index 7b956804..bb435262 100644
--- a/src/EntityFrameworkCore.Generator.Core/ModelGenerator.cs
+++ b/src/EntityFrameworkCore.Generator.Core/ModelGenerator.cs
@@ -1,7 +1,4 @@
-using System;
-using System.Collections.Generic;
using System.Data;
-using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
@@ -12,12 +9,17 @@
using Humanizer;
using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Scaffolding.Metadata;
using Microsoft.EntityFrameworkCore.Scaffolding.Metadata.Internal;
using Microsoft.EntityFrameworkCore.SqlServer.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.Logging;
+using static Npgsql.Replication.PgOutput.Messages.RelationMessage;
+
+using Model = EntityFrameworkCore.Generator.Metadata.Generation.Model;
+using Property = EntityFrameworkCore.Generator.Metadata.Generation.Property;
using PropertyCollection = EntityFrameworkCore.Generator.Metadata.Generation.PropertyCollection;
namespace EntityFrameworkCore.Generator;
@@ -96,7 +98,7 @@ private Entity GetEntity(EntityContext entityContext, DatabaseTable tableSchema,
?? CreateEntity(entityContext, tableSchema);
if (!entity.Properties.IsProcessed)
- CreateProperties(entity, tableSchema.Columns);
+ CreateProperties(entity, tableSchema);
if (processRelationships && !entity.Relationships.IsProcessed)
CreateRelationships(entityContext, entity, tableSchema);
@@ -148,7 +150,7 @@ private Entity CreateEntity(EntityContext entityContext, DatabaseTable tableSche
entity.IsView = tableSchema is DatabaseView;
bool? isTemporal = tableSchema[SqlServerAnnotationNames.IsTemporal] as bool?;
- if (isTemporal == true)
+ if (isTemporal == true && _options.Data.Mapping.Temporal)
{
entity.TemporalTableName = tableSchema[SqlServerAnnotationNames.TemporalHistoryTableName] as string;
entity.TemporalTableSchema = tableSchema[SqlServerAnnotationNames.TemporalHistoryTableSchema] as string;
@@ -170,8 +172,9 @@ private Entity CreateEntity(EntityContext entityContext, DatabaseTable tableSche
}
- private void CreateProperties(Entity entity, IEnumerable columns)
+ private void CreateProperties(Entity entity, DatabaseTable tableSchema)
{
+ var columns = tableSchema.Columns;
foreach (var column in columns)
{
var table = column.Table;
@@ -212,6 +215,7 @@ private void CreateProperties(Entity entity, IEnumerable columns
property.IsNullable = column.IsNullable;
property.IsRowVersion = column.IsRowVersion();
+ property.IsConcurrencyToken = (bool?)column[ScaffoldingAnnotationNames.ConcurrencyToken] == true;
property.IsPrimaryKey = table.PrimaryKey?.Columns.Contains(column) == true;
property.IsForeignKey = table.ForeignKeys.Any(c => c.Columns.Contains(column));
@@ -219,7 +223,9 @@ private void CreateProperties(Entity entity, IEnumerable columns
property.IsUnique = table.UniqueConstraints.Any(c => c.Columns.Contains(column))
|| table.Indexes.Where(i => i.IsUnique).Any(c => c.Columns.Contains(column));
+ property.DefaultValue = column.DefaultValue;
property.Default = column.DefaultValueSql;
+
property.ValueGenerated = column.ValueGenerated;
if (property.ValueGenerated == null && !string.IsNullOrWhiteSpace(column.ComputedColumnSql))
@@ -231,10 +237,67 @@ private void CreateProperties(Entity entity, IEnumerable columns
property.SystemType = mapping.ClrType;
property.Size = mapping.Size;
+ // overwrite row version type
+ if (property.IsRowVersion == true && _options.Data.Mapping.RowVersion != RowVersionMapping.ByteArray && property.SystemType == typeof(byte[]))
+ {
+ property.SystemType = _options.Data.Mapping.RowVersion switch
+ {
+ RowVersionMapping.ByteArray => typeof(byte[]),
+ RowVersionMapping.Long => typeof(long),
+ RowVersionMapping.ULong => typeof(ulong),
+ _ => typeof(byte[])
+ };
+ }
+
property.IsProcessed = true;
}
entity.Properties.IsProcessed = true;
+
+
+ bool? isTemporal = tableSchema[SqlServerAnnotationNames.IsTemporal] as bool?;
+ if (isTemporal != true || _options.Data.Mapping.Temporal)
+ return;
+
+ // add temporal period columns
+ var temporalStartColumn = tableSchema[SqlServerAnnotationNames.TemporalPeriodStartColumnName] as string
+ ?? tableSchema[SqlServerAnnotationNames.TemporalPeriodStartPropertyName] as string;
+
+ var temporalStart = entity.Properties.ByColumn(temporalStartColumn);
+
+ if (temporalStart == null)
+ {
+ temporalStart = new Property { Entity = entity, ColumnName = temporalStartColumn };
+ entity.Properties.Add(temporalStart);
+ }
+
+ temporalStart.PropertyName = ToPropertyName(entity.EntityClass, temporalStartColumn);
+ temporalStart.ValueGenerated = ValueGenerated.OnAddOrUpdate;
+ temporalStart.StoreType = "datetime2";
+ temporalStart.DataType = DbType.DateTime2;
+ temporalStart.SystemType = typeof(DateTime);
+
+ temporalStart.IsProcessed = true;
+
+
+ var temporalEndColumn = tableSchema[SqlServerAnnotationNames.TemporalPeriodEndColumnName] as string
+ ?? tableSchema[SqlServerAnnotationNames.TemporalPeriodEndPropertyName] as string;
+
+ var temporalEnd = entity.Properties.ByColumn(temporalEndColumn);
+
+ if (temporalEnd == null)
+ {
+ temporalEnd = new Property { Entity = entity, ColumnName = temporalEndColumn };
+ entity.Properties.Add(temporalEnd);
+ }
+
+ temporalEnd.PropertyName = ToPropertyName(entity.EntityClass, temporalEndColumn);
+ temporalEnd.ValueGenerated = ValueGenerated.OnAddOrUpdate;
+ temporalEnd.StoreType = "datetime2";
+ temporalEnd.DataType = DbType.DateTime2;
+ temporalEnd.SystemType = typeof(DateTime);
+
+ temporalEnd.IsProcessed = true;
}
diff --git a/src/EntityFrameworkCore.Generator.Core/OptionMapper.cs b/src/EntityFrameworkCore.Generator.Core/OptionMapper.cs
index aa2691dc..f2c0587c 100644
--- a/src/EntityFrameworkCore.Generator.Core/OptionMapper.cs
+++ b/src/EntityFrameworkCore.Generator.Core/OptionMapper.cs
@@ -155,6 +155,8 @@ private static void MapMapping(MappingClassOptions option, MappingClass mapping)
option.Namespace = mapping.Namespace;
option.Directory = mapping.Directory;
option.Document = mapping.Document;
+ option.Temporal = mapping.Temporal;
+ option.RowVersion = mapping.RowVersion;
}
private static void MapEntity(EntityClassOptions option, EntityClass entity)
@@ -267,6 +269,7 @@ private static TemplateOptions MapTemplate(VariableDictionary variables, Templat
BaseClass = template.BaseClass,
Directory = template.Directory,
Overwrite = template.Overwrite,
+ Merge = template.Merge,
};
if (template.Parameters == null || template.Parameters.Count == 0)
diff --git a/src/EntityFrameworkCore.Generator.Core/Options/ClassOptionsBase.cs b/src/EntityFrameworkCore.Generator.Core/Options/ClassOptionsBase.cs
index aab4e498..2c34ba57 100644
--- a/src/EntityFrameworkCore.Generator.Core/Options/ClassOptionsBase.cs
+++ b/src/EntityFrameworkCore.Generator.Core/Options/ClassOptionsBase.cs
@@ -51,13 +51,4 @@ public string Directory
///
[DefaultValue(false)]
public bool Document { get; set; }
-
- ///
- /// Gets or sets a value indicating whether to use file-scoped namespace.
- ///
- ///
- /// true to use file-coped namespace; otherwise, false.
- ///
- [Obsolete("Use ProjectOptions.FileScopedNamespace instead")]
- public bool? FileScopedNamespace { get; set; }
}
diff --git a/src/EntityFrameworkCore.Generator.Core/Options/ContextNaming.cs b/src/EntityFrameworkCore.Generator.Core/Options/ContextNaming.cs
index 4c29e7a7..1a18a510 100644
--- a/src/EntityFrameworkCore.Generator.Core/Options/ContextNaming.cs
+++ b/src/EntityFrameworkCore.Generator.Core/Options/ContextNaming.cs
@@ -1,4 +1,4 @@
-using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore;
namespace EntityFrameworkCore.Generator.Options;
@@ -21,4 +21,4 @@ public enum ContextNaming
/// Add 'DataSet' to the end of the entity name.
///
Suffix = 2
-}
\ No newline at end of file
+}
diff --git a/src/EntityFrameworkCore.Generator.Core/Options/MappingClassOptions.cs b/src/EntityFrameworkCore.Generator.Core/Options/MappingClassOptions.cs
index 1fd84530..ae47b405 100644
--- a/src/EntityFrameworkCore.Generator.Core/Options/MappingClassOptions.cs
+++ b/src/EntityFrameworkCore.Generator.Core/Options/MappingClassOptions.cs
@@ -1,4 +1,6 @@
-namespace EntityFrameworkCore.Generator.Options;
+using System.ComponentModel;
+
+namespace EntityFrameworkCore.Generator.Options;
///
/// EntityFramework mapping class generation options
@@ -15,4 +17,24 @@ public MappingClassOptions(VariableDictionary variables, string prefix)
Namespace = "{Project.Namespace}.Data.Mapping";
Directory = @"{Project.Directory}\Data\Mapping";
}
-}
\ No newline at end of file
+
+ ///
+ /// Gets or sets if temporal table mapping is enabled. Default true
+ ///
+ ///
+ /// If temporal table mapping is enabled.
+ ///
+ [DefaultValue(true)]
+ public bool Temporal { get; set; } = true;
+
+ ///
+ /// Gets or sets how row version properties should be mapped.
+ ///
+ ///
+ /// How row version properties should be mapped.
+ ///
+ ///
+ [DefaultValue(RowVersionMapping.ByteArray)]
+ public RowVersionMapping RowVersion { get; set; } = RowVersionMapping.ByteArray;
+
+}
diff --git a/src/EntityFrameworkCore.Generator.Core/Options/RowVersionMapping.cs b/src/EntityFrameworkCore.Generator.Core/Options/RowVersionMapping.cs
new file mode 100644
index 00000000..818af7ee
--- /dev/null
+++ b/src/EntityFrameworkCore.Generator.Core/Options/RowVersionMapping.cs
@@ -0,0 +1,20 @@
+namespace EntityFrameworkCore.Generator.Options;
+
+///
+/// How row versions should be mapped
+///
+public enum RowVersionMapping
+{
+ ///
+ /// Map as byte array, default
+ ///
+ ByteArray = 0,
+ ///
+ /// Map as a long
+ ///
+ Long = 1,
+ ///
+ /// Map as a ulong
+ ///
+ ULong = 2,
+}
diff --git a/src/EntityFrameworkCore.Generator.Core/Options/TemplateOptions.cs b/src/EntityFrameworkCore.Generator.Core/Options/TemplateOptions.cs
index ed215b1a..6f6be757 100644
--- a/src/EntityFrameworkCore.Generator.Core/Options/TemplateOptions.cs
+++ b/src/EntityFrameworkCore.Generator.Core/Options/TemplateOptions.cs
@@ -10,7 +10,7 @@ public class TemplateOptions : OptionsBase
///
/// Initializes a new instance of the class.
///
- /// The shared variables dictionary.
+ /// The shared variable dictionary.
/// The variable key prefix.
public TemplateOptions(VariableDictionary variables, string prefix)
: base(variables, AppendPrefix(prefix, "Template"))
@@ -80,13 +80,21 @@ public string Directory
}
///
- /// Gets or sets a value indicating whether the generated file will be over written.
+ /// Gets or sets a value indicating whether the generated file will be overwritten.
///
///
/// true to overwrite generated file; otherwise, false.
///
public bool Overwrite { get; set; }
+ ///
+ /// Gets or sets a value indicating whether the generated file will be merged via region replacement.
+ ///
+ ///
+ /// true to merged via region replacement; otherwise, false.
+ ///
+ public bool Merge { get; set; }
+
///
/// Gets or sets the template parameters.
///
diff --git a/src/EntityFrameworkCore.Generator.Core/Parsing/RegionReplace.cs b/src/EntityFrameworkCore.Generator.Core/Parsing/RegionReplace.cs
new file mode 100644
index 00000000..93bc1eb6
--- /dev/null
+++ b/src/EntityFrameworkCore.Generator.Core/Parsing/RegionReplace.cs
@@ -0,0 +1,59 @@
+using System.Text;
+
+namespace EntityFrameworkCore.Generator.Parsing;
+
+public class RegionReplace
+{
+ public RegionReplace(RegionParser regionParser = null)
+ {
+ RegionParser = regionParser ?? new RegionParser();
+ }
+
+ protected RegionParser RegionParser { get; }
+
+ public void MergeFile(string fullPath, string outputContent)
+ {
+ var originalContent = File.ReadAllText(fullPath);
+
+ var finalContent = MergeContent(originalContent, outputContent);
+
+ File.WriteAllText(fullPath, finalContent);
+ }
+
+ public string MergeContent(string originalContent, string outputContent)
+ {
+ var outputRegions = RegionParser.ParseRegions(outputContent);
+
+ var originalRegions = RegionParser.ParseRegions(originalContent);
+ var originalBuilder = new StringBuilder(originalContent);
+
+ int offset = 0;
+ foreach (var pair in outputRegions)
+ {
+ var outputRegion = pair.Value;
+ if (!originalRegions.TryGetValue(pair.Key, out var originalRegion))
+ {
+ // log error
+ continue;
+ }
+
+ int startIndex = originalRegion.StartIndex + offset;
+ int beforeReplace = originalBuilder.Length;
+ int length = (originalRegion.EndIndex + offset) - startIndex;
+
+ originalBuilder.Remove(startIndex, length);
+ originalBuilder.Insert(startIndex, outputRegion.Content);
+
+ int afterReplace = originalBuilder.Length;
+
+ offset += (afterReplace - beforeReplace);
+ }
+
+ var finalContent = originalBuilder.ToString();
+
+ if (originalContent == finalContent)
+ return finalContent;
+
+ return finalContent;
+ }
+}
diff --git a/src/EntityFrameworkCore.Generator.Core/Scripts/ContextScriptVariables.cs b/src/EntityFrameworkCore.Generator.Core/Scripts/ContextScriptVariables.cs
index 8a4777d3..a8460544 100644
--- a/src/EntityFrameworkCore.Generator.Core/Scripts/ContextScriptVariables.cs
+++ b/src/EntityFrameworkCore.Generator.Core/Scripts/ContextScriptVariables.cs
@@ -1,4 +1,4 @@
-using EntityFrameworkCore.Generator.Metadata.Generation;
+using EntityFrameworkCore.Generator.Metadata.Generation;
using EntityFrameworkCore.Generator.Options;
namespace EntityFrameworkCore.Generator.Scripts;
@@ -12,4 +12,4 @@ public ContextScriptVariables(EntityContext entityContext, GeneratorOptions gene
}
public EntityContext EntityContext { get; }
-}
\ No newline at end of file
+}
diff --git a/src/EntityFrameworkCore.Generator.Core/Scripts/ScriptTemplateBase.cs b/src/EntityFrameworkCore.Generator.Core/Scripts/ScriptTemplateBase.cs
index 70d909ee..fdca6c91 100644
--- a/src/EntityFrameworkCore.Generator.Core/Scripts/ScriptTemplateBase.cs
+++ b/src/EntityFrameworkCore.Generator.Core/Scripts/ScriptTemplateBase.cs
@@ -1,7 +1,9 @@
-using System.IO;
+using System.IO;
+using System.Text;
using EntityFrameworkCore.Generator.Extensions;
using EntityFrameworkCore.Generator.Options;
+using EntityFrameworkCore.Generator.Parsing;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Scripting;
@@ -23,14 +25,20 @@ protected ScriptTemplateBase(ILoggerFactory loggerFactory, GeneratorOptions gene
TemplateOptions = templateOptions;
GeneratorOptions = generatorOptions;
+ RegionReplace = new RegionReplace();
+
}
protected ILogger Logger { get; }
+ protected RegionReplace RegionReplace { get; }
+
+
public TemplateOptions TemplateOptions { get; }
public GeneratorOptions GeneratorOptions { get; }
+
protected virtual void WriteCode()
{
var templatePath = TemplateOptions.TemplatePath;
@@ -51,7 +59,7 @@ protected virtual void WriteCode()
var exists = File.Exists(path);
- if (exists && !TemplateOptions.Overwrite)
+ if (exists && !(TemplateOptions.Merge || TemplateOptions.Overwrite))
{
Logger.LogDebug("Skipping template '{template}' because output '{fileName}' already exists.", templatePath, fileName);
return;
@@ -70,7 +78,10 @@ protected virtual void WriteCode()
return;
}
- File.WriteAllText(path, content);
+ if (exists && TemplateOptions.Merge && !TemplateOptions.Overwrite)
+ RegionReplace.MergeFile(path, content);
+ else
+ File.WriteAllText(path, content);
}
protected virtual string ExecuteScript()
@@ -140,4 +151,4 @@ protected Script LoadScript(string scriptPath)
return _scriptTemplate;
}
-}
\ No newline at end of file
+}
diff --git a/src/EntityFrameworkCore.Generator.Core/Serialization/MappingClass.cs b/src/EntityFrameworkCore.Generator.Core/Serialization/MappingClass.cs
index 27007d98..6665ee6b 100644
--- a/src/EntityFrameworkCore.Generator.Core/Serialization/MappingClass.cs
+++ b/src/EntityFrameworkCore.Generator.Core/Serialization/MappingClass.cs
@@ -1,3 +1,7 @@
+using System.ComponentModel;
+
+using EntityFrameworkCore.Generator.Options;
+
namespace EntityFrameworkCore.Generator.Serialization;
///
@@ -13,4 +17,24 @@ public MappingClass()
Namespace = "{Project.Namespace}.Data.Mapping";
Directory = @"{Project.Directory}\Data\Mapping";
}
+
+ ///
+ /// Gets or sets if temporal table mapping is enabled. Default true
+ ///
+ ///
+ /// If temporal table mapping is enabled.
+ ///
+ [DefaultValue(true)]
+ public bool Temporal { get; set; } = true;
+
+ ///
+ /// Gets or sets how row version properties should be mapped.
+ ///
+ ///
+ /// How row version properties should be mapped.
+ ///
+ ///
+ [DefaultValue(RowVersionMapping.ByteArray)]
+ public RowVersionMapping RowVersion { get; set; } = RowVersionMapping.ByteArray;
+
}
diff --git a/src/EntityFrameworkCore.Generator.Core/Serialization/TemplateModel.cs b/src/EntityFrameworkCore.Generator.Core/Serialization/TemplateModel.cs
index 1e1fc205..57da6b35 100644
--- a/src/EntityFrameworkCore.Generator.Core/Serialization/TemplateModel.cs
+++ b/src/EntityFrameworkCore.Generator.Core/Serialization/TemplateModel.cs
@@ -3,7 +3,7 @@
namespace EntityFrameworkCore.Generator.Serialization;
///
-/// Sript template options
+/// Script template options
///
public class TemplateModel
{
@@ -49,13 +49,21 @@ public class TemplateModel
public string Directory { get; set; }
///
- /// Gets or sets a value indicating whether the generated file will be over written.
+ /// Gets or sets a value indicating whether the generated file will be overwritten.
///
///
/// true to overwrite generated file; otherwise, false.
///
public bool Overwrite { get; set; }
+ ///
+ /// Gets or sets a value indicating whether the generated file will be merged via region replacement.
+ ///
+ ///
+ /// true to merged via region replacement; otherwise, false.
+ ///
+ public bool Merge { get; set; }
+
///
/// Gets or sets the template parameters.
///
diff --git a/src/EntityFrameworkCore.Generator.Core/Templates/CodeTemplateBase.cs b/src/EntityFrameworkCore.Generator.Core/Templates/CodeTemplateBase.cs
index 1649ead3..b9d4239c 100644
--- a/src/EntityFrameworkCore.Generator.Core/Templates/CodeTemplateBase.cs
+++ b/src/EntityFrameworkCore.Generator.Core/Templates/CodeTemplateBase.cs
@@ -15,12 +15,12 @@ protected CodeTemplateBase(GeneratorOptions options)
{
Options = options;
CodeBuilder = new IndentedStringBuilder();
- RegionParser = new RegionParser();
+ RegionReplace = new RegionReplace();
}
public GeneratorOptions Options { get; }
- protected RegionParser RegionParser { get; }
+ protected RegionReplace RegionReplace { get; }
protected IndentedStringBuilder CodeBuilder { get; }
@@ -35,47 +35,10 @@ public virtual void WriteCode(string path)
var output = WriteCode();
if (File.Exists(fullPath))
- MergeOutput(fullPath, output);
+ RegionReplace.MergeFile(fullPath, output);
else
File.WriteAllText(fullPath, output);
}
public abstract string WriteCode();
-
- protected virtual void MergeOutput(string fullPath, string outputContent)
- {
- var outputRegions = RegionParser.ParseRegions(outputContent);
-
- var originalContent = File.ReadAllText(fullPath);
- var originalRegions = RegionParser.ParseRegions(originalContent);
- var originalBuilder = new StringBuilder(originalContent);
-
- int offset = 0;
- foreach (var pair in outputRegions)
- {
- var outputRegion = pair.Value;
- if (!originalRegions.TryGetValue(pair.Key, out var originalRegion))
- {
- // log error
- continue;
- }
-
- int startIndex = originalRegion.StartIndex + offset;
- int beforeReplace = originalBuilder.Length;
- int length = (originalRegion.EndIndex + offset) - startIndex;
-
- originalBuilder.Remove(startIndex, length);
- originalBuilder.Insert(startIndex, outputRegion.Content);
-
- int afterReplace = originalBuilder.Length;
-
- offset = offset + (afterReplace - beforeReplace);
- }
-
- var finalContent = originalBuilder.ToString();
- if (originalContent == finalContent)
- return;
-
- File.WriteAllText(fullPath, finalContent);
- }
}
diff --git a/src/EntityFrameworkCore.Generator.Core/Templates/MappingClassTemplate.cs b/src/EntityFrameworkCore.Generator.Core/Templates/MappingClassTemplate.cs
index d9b37d52..8a75642f 100644
--- a/src/EntityFrameworkCore.Generator.Core/Templates/MappingClassTemplate.cs
+++ b/src/EntityFrameworkCore.Generator.Core/Templates/MappingClassTemplate.cs
@@ -1,5 +1,5 @@
+using System.Data;
using System.Globalization;
-using System.Linq;
using EntityFrameworkCore.Generator.Extensions;
using EntityFrameworkCore.Generator.Metadata.Generation;
@@ -263,10 +263,21 @@ private void GeneratePropertyMapping(Property property)
if (property.IsRowVersion == true)
{
+ if (property.DataType == DbType.Binary && property.SystemType != typeof(byte[]))
+ {
+ CodeBuilder.AppendLine();
+ CodeBuilder.Append(".HasConversion()");
+ }
CodeBuilder.AppendLine();
CodeBuilder.Append(".IsRowVersion()");
}
+ if (property.IsConcurrencyToken == true)
+ {
+ CodeBuilder.AppendLine();
+ CodeBuilder.Append(".IsConcurrencyToken()");
+ }
+
CodeBuilder.AppendLine();
CodeBuilder.Append($".HasColumnName({property.ColumnName.ToLiteral()})");
@@ -282,7 +293,13 @@ private void GeneratePropertyMapping(Property property)
CodeBuilder.Append($".HasMaxLength({property.Size.Value.ToString(CultureInfo.InvariantCulture)})");
}
- if (!string.IsNullOrEmpty(property.Default))
+ // only use for simple types
+ if (property.DefaultValue is bool or int or long or byte or double or float or short)
+ {
+ CodeBuilder.AppendLine();
+ CodeBuilder.Append($".HasDefaultValue({property.DefaultValue?.ToString()?.ToLowerInvariant()})");
+ }
+ else if (!string.IsNullOrEmpty(property.Default))
{
CodeBuilder.AppendLine();
CodeBuilder.Append($".HasDefaultValueSql({property.Default.ToLiteral()})");
diff --git a/src/EntityFrameworkCore.Generator.Core/Templates/QueryExtensionTemplate.cs b/src/EntityFrameworkCore.Generator.Core/Templates/QueryExtensionTemplate.cs
index 6a8f3c3f..effcf480 100644
--- a/src/EntityFrameworkCore.Generator.Core/Templates/QueryExtensionTemplate.cs
+++ b/src/EntityFrameworkCore.Generator.Core/Templates/QueryExtensionTemplate.cs
@@ -158,6 +158,10 @@ private void GenerateUniqueMethod(Method method, bool async = false)
CodeBuilder.AppendLine("/// ");
CodeBuilder.AppendLine("/// An to filter.");
AppendDocumentation(method);
+
+ if (async)
+ CodeBuilder.AppendLine("/// A to observe while waiting for the task to complete.");
+
CodeBuilder.AppendLine($"/// An instance of or null if not found.");
}
@@ -210,6 +214,10 @@ private void GenerateKeyMethod(Method method, bool async = false)
CodeBuilder.AppendLine("/// ");
CodeBuilder.AppendLine("/// An to filter.");
AppendDocumentation(method);
+
+ if (async)
+ CodeBuilder.AppendLine("/// A to observe while waiting for the task to complete.");
+
CodeBuilder.AppendLine($"/// An instance of or null if not found.");
}
diff --git a/src/EntityFrameworkCore.Generator.Core/Templates/ValidatorClassTemplate.cs b/src/EntityFrameworkCore.Generator.Core/Templates/ValidatorClassTemplate.cs
index aeff3ba8..dfba69f5 100644
--- a/src/EntityFrameworkCore.Generator.Core/Templates/ValidatorClassTemplate.cs
+++ b/src/EntityFrameworkCore.Generator.Core/Templates/ValidatorClassTemplate.cs
@@ -105,7 +105,7 @@ private void GenerateConstructor()
if (property.IsRequired && property.SystemType == typeof(string))
CodeBuilder.AppendLine($"RuleFor(p => p.{propertyName}).NotEmpty();");
- if (property.Size.HasValue && property.SystemType == typeof(string))
+ if (property.Size.HasValue && property.SystemType == typeof(string) && property.Size > 0)
CodeBuilder.AppendLine($"RuleFor(p => p.{propertyName}).MaximumLength({property.Size});");
}
diff --git a/src/EntityFrameworkCore.Generator/EntityFrameworkCore.Generator.csproj b/src/EntityFrameworkCore.Generator/EntityFrameworkCore.Generator.csproj
index 4a08c3b0..d53549cc 100644
--- a/src/EntityFrameworkCore.Generator/EntityFrameworkCore.Generator.csproj
+++ b/src/EntityFrameworkCore.Generator/EntityFrameworkCore.Generator.csproj
@@ -1,7 +1,7 @@
Exe
- net6.0;net8.0
+ net8.0
efg
true
1591,EF1001
@@ -10,7 +10,7 @@
-
+
diff --git a/src/EntityFrameworkCore.Generator/InitializeCommand.cs b/src/EntityFrameworkCore.Generator/InitializeCommand.cs
index 64a11601..9f359ac2 100644
--- a/src/EntityFrameworkCore.Generator/InitializeCommand.cs
+++ b/src/EntityFrameworkCore.Generator/InitializeCommand.cs
@@ -94,11 +94,13 @@ private Serialization.GeneratorModel CreateOptionsFile(string optionsFile)
{
var options = new Serialization.GeneratorModel();
- options.Project.Namespace = Directory.CreateDirectory(Environment.CurrentDirectory)?.Name ?? "Project.Core";
+ options.Project.Namespace = Directory.CreateDirectory(Environment.CurrentDirectory).Name ?? "Project.Core";
options.Project.Directory = ".\\";
options.Project.Nullable = true;
options.Project.FileScopedNamespace = true;
+ options.Data.Mapping.RowVersion = RowVersionMapping.Long;
+
// default all to generate
options.Data.Query.Generate = true;
options.Model.Read.Generate = true;
@@ -106,7 +108,7 @@ private Serialization.GeneratorModel CreateOptionsFile(string optionsFile)
options.Model.Update.Generate = true;
options.Model.Validator.Generate = true;
options.Model.Mapper.Generate = true;
-
+
Logger.LogInformation($"Creating options file: {optionsFile}");
return options;
diff --git a/test/EntityFrameworkCore.Generator.Core.Tests/EntityFrameworkCore.Generator.Core.Tests.csproj b/test/EntityFrameworkCore.Generator.Core.Tests/EntityFrameworkCore.Generator.Core.Tests.csproj
index 2974bc5d..bcf2c47b 100644
--- a/test/EntityFrameworkCore.Generator.Core.Tests/EntityFrameworkCore.Generator.Core.Tests.csproj
+++ b/test/EntityFrameworkCore.Generator.Core.Tests/EntityFrameworkCore.Generator.Core.Tests.csproj
@@ -1,6 +1,6 @@
-
+
- net6.0
+ net8.0
false
1591,EF1001
@@ -27,8 +27,8 @@
-
-
+
+
all
runtime; build; native; contentfiles; analyzers
diff --git a/test/EntityFrameworkCore.Generator.Core.Tests/ModelGeneratorTests.cs b/test/EntityFrameworkCore.Generator.Core.Tests/ModelGeneratorTests.cs
index fbf0654b..61535c84 100644
--- a/test/EntityFrameworkCore.Generator.Core.Tests/ModelGeneratorTests.cs
+++ b/test/EntityFrameworkCore.Generator.Core.Tests/ModelGeneratorTests.cs
@@ -7,6 +7,7 @@
using Microsoft.EntityFrameworkCore.Scaffolding.Metadata;
using Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal;
using Microsoft.EntityFrameworkCore.Storage;
+using Microsoft.EntityFrameworkCore.Storage.Json;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Microsoft.Extensions.Logging.Abstractions;
@@ -570,9 +571,8 @@ private static SqlServerTypeMappingSource CreateTypeMappingSource()
#pragma warning disable EF1001 // Internal EF Core API usage.
var sqlServerTypeMappingSource = new SqlServerTypeMappingSource(
new TypeMappingSourceDependencies(
- new ValueConverterSelector(
- new ValueConverterSelectorDependencies()
- ),
+ new ValueConverterSelector(new ValueConverterSelectorDependencies()),
+ new JsonValueReaderWriterSource(new JsonValueReaderWriterSourceDependencies()),
Enumerable.Empty()
),
new RelationalTypeMappingSourceDependencies(Enumerable.Empty())