Skip to content

Commit b1a61a8

Browse files
committed
Add support for memory optimised tables
1 parent e656d5d commit b1a61a8

File tree

20 files changed

+371
-22
lines changed

20 files changed

+371
-22
lines changed

EntityFramework.Reverse.POCO.Generator/EF.Reverse.POCO.v3.ttinclude

Lines changed: 174 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3649,12 +3649,14 @@
36493649
UseLazyLoadingProxies = Settings.UseLazyLoading && Settings.IsEfCore3Plus(),
36503650
SqlParameter = Settings.SqlParameter(),
36513651
Triggers = _tables.Where(x => !string.IsNullOrEmpty(x.Table.TriggerName))
3652-
.Select(x => new Trigger { TableName = x.Table.NameHumanCase, TriggerName = x.Table.TriggerName }).ToList()
3652+
.Select(x => new Trigger { TableName = x.Table.NameHumanCase, TriggerName = x.Table.TriggerName }).ToList(),
3653+
MemoryOptimisedTables = _tables.Where(x => x.Table.IsMemoryOptimised).Select(x => x.Table.NameHumanCase).ToList()
36533654
};
36543655

3655-
data.hasIndexes = data.indexes.Any();
3656-
data.hasTriggers = data.Triggers.Any();
3657-
data.hasSequences = data.Sequences.Any();
3656+
data.hasIndexes = data.indexes.Any();
3657+
data.hasTriggers = data.Triggers.Any();
3658+
data.hasSequences = data.Sequences.Any();
3659+
data.hasMemoryOptimisedTables = data.MemoryOptimisedTables.Any();
36583660

36593661
var co = new CodeOutput(string.Empty, filename, "Database context", Settings.ContextFolder, _globalUsings);
36603662
co.AddUsings(_template.DatabaseContextUsings(data));
@@ -4355,6 +4357,12 @@
43554357
AddIndexesToFilters(rawIndexes);
43564358
SetPrimaryKeys();
43574359
AddForeignKeysToFilters(rawForeignKeys);
4360+
4361+
if (Settings.IsEfCore6Plus())
4362+
{
4363+
var rawMemoryOptimisedTables = DatabaseReader.ReadMemoryOptimisedTables();
4364+
AddMemoryOptimisedTablesToFilters(rawMemoryOptimisedTables);
4365+
}
43584366

43594367
if (Settings.IsEfCore7Plus())
43604368
{
@@ -4718,6 +4726,30 @@
47184726
}
47194727
}
47204728

4729+
private void AddMemoryOptimisedTablesToFilters(List<RawMemoryOptimisedTable> memoryOptimisedTables)
4730+
{
4731+
if (memoryOptimisedTables == null || !memoryOptimisedTables.Any())
4732+
return;
4733+
4734+
foreach (var filterKeyValuePair in FilterList.GetFilters())
4735+
{
4736+
var filter = filterKeyValuePair.Value;
4737+
4738+
Table t = null;
4739+
foreach (var trigger in memoryOptimisedTables)
4740+
{
4741+
// Lookup table
4742+
if (t == null || t.DbName != trigger.TableName || t.Schema.DbName != trigger.SchemaName)
4743+
t = filter.Tables.GetTable(trigger.TableName, trigger.SchemaName);
4744+
4745+
if (t == null)
4746+
continue;
4747+
4748+
t.IsMemoryOptimised = true;
4749+
}
4750+
}
4751+
}
4752+
47214753
private void AddExtendedPropertiesToFilters(List<RawExtendedProperty> extendedProperties)
47224754
{
47234755
if (extendedProperties == null || !extendedProperties.Any())
@@ -12215,6 +12247,16 @@ and limitations under the License.
1221512247
protected abstract string EnumSQL(string table, string nameField, string valueField);
1221612248
protected abstract string SequenceSQL();
1221712249
protected abstract string TriggerSQL();
12250+
protected abstract string[] MemoryOptimisedSQL();
12251+
12252+
protected enum MemoryOptimised
12253+
{
12254+
CompatibilityLevel,
12255+
InMemorySupported,
12256+
TableList,
12257+
12258+
Count // This is always the last value
12259+
}
1221812260

1221912261
// Synonym
1222012262
protected abstract string SynonymTableSQLSetup();
@@ -13112,6 +13154,62 @@ and limitations under the License.
1311213154
return result;
1311313155
}
1311413156

13157+
public List<RawMemoryOptimisedTable> ReadMemoryOptimisedTables()
13158+
{
13159+
if (DatabaseReaderPlugin != null)
13160+
return DatabaseReaderPlugin.ReadMemoryOptimisedTables();
13161+
13162+
var result = new List<RawMemoryOptimisedTable>();
13163+
try
13164+
{
13165+
using (var conn = _factory.CreateConnection())
13166+
{
13167+
if (conn == null)
13168+
return result;
13169+
13170+
conn.ConnectionString = Settings.ConnectionString;
13171+
conn.Open();
13172+
13173+
var cmd = GetCmd(conn);
13174+
if (cmd == null)
13175+
return result;
13176+
13177+
var sql = MemoryOptimisedSQL();
13178+
if (sql == null || sql.Length != (int) MemoryOptimised.Count)
13179+
return result;
13180+
13181+
cmd.CommandText = sql[(int) MemoryOptimised.CompatibilityLevel];
13182+
var compatibilityLevel = Convert.ToInt16(cmd.ExecuteScalar());
13183+
if(compatibilityLevel < 130)
13184+
return result;
13185+
13186+
cmd.CommandText = sql[(int) MemoryOptimised.InMemorySupported];
13187+
var inMemorySupported = Convert.ToBoolean(cmd.ExecuteScalar());
13188+
if(!inMemorySupported)
13189+
return result;
13190+
13191+
cmd.CommandText = sql[(int) MemoryOptimised.TableList];
13192+
using (var rdr = cmd.ExecuteReader())
13193+
{
13194+
while (rdr.Read())
13195+
{
13196+
var index = new RawMemoryOptimisedTable
13197+
(
13198+
rdr["SchemaName"].ToString().Trim(),
13199+
rdr["TableName"].ToString().Trim()
13200+
);
13201+
result.Add(index);
13202+
}
13203+
}
13204+
}
13205+
}
13206+
catch (Exception)
13207+
{
13208+
// Memory optimised tables are not supported
13209+
}
13210+
return result;
13211+
}
13212+
1311513213
private static string GetReaderString(DbDataReader rdr, string name)
1311613214
{
1311713215
try
@@ -13311,13 +13409,14 @@ and limitations under the License.
1331113409

1331213410
public interface IDatabaseReaderPlugin
1331313411
{
13314-
List<RawTable> ReadTables();
13315-
List<RawForeignKey> ReadForeignKeys();
13316-
List<RawIndex> ReadIndexes();
13317-
List<RawExtendedProperty> ReadExtendedProperties();
13318-
List<RawStoredProcedure> ReadStoredProcs();
13319-
List<RawSequence> ReadSequences();
13320-
List<RawTrigger> ReadTriggers();
13412+
List<RawTable> ReadTables();
13413+
List<RawForeignKey> ReadForeignKeys();
13414+
List<RawIndex> ReadIndexes();
13415+
List<RawExtendedProperty> ReadExtendedProperties();
13416+
List<RawStoredProcedure> ReadStoredProcs();
13417+
List<RawSequence> ReadSequences();
13418+
List<RawTrigger> ReadTriggers();
13419+
List<RawMemoryOptimisedTable> ReadMemoryOptimisedTables();
1332113420

1332213421
IDatabaseToPropertyType GetDatabaseToPropertyTypeMapping();
1332313422
}
@@ -13439,6 +13538,11 @@ and limitations under the License.
1343913538
return string.Empty;
1344013539
}
1344113540

13541+
protected override string[] MemoryOptimisedSQL()
13542+
{
13543+
return null;
13544+
}
13545+
1344213546
protected override string SynonymTableSQLSetup()
1344313547
{
1344413548
return string.Empty;
@@ -13562,6 +13666,11 @@ and limitations under the License.
1356213666
return string.Empty;
1356313667
}
1356413668

13669+
protected override string[] MemoryOptimisedSQL()
13670+
{
13671+
return null;
13672+
}
13673+
1356513674
protected override string SynonymTableSQLSetup()
1356613675
{
1356713676
return string.Empty;
@@ -13703,6 +13812,11 @@ and limitations under the License.
1370313812
return string.Empty;
1370413813
}
1370513814

13815+
protected override string[] MemoryOptimisedSQL()
13816+
{
13817+
return null;
13818+
}
13819+
1370613820
protected override string SynonymTableSQLSetup()
1370713821
{
1370813822
return string.Empty;
@@ -13959,6 +14073,11 @@ FROM INFORMATION_SCHEMA.triggers
1395914073
ORDER BY SchemaName, TableName, TriggerName;";
1396014074
}
1396114075

14076+
protected override string[] MemoryOptimisedSQL()
14077+
{
14078+
return null;
14079+
}
14080+
1396214081
protected override string SynonymTableSQLSetup()
1396314082
{
1396414083
return string.Empty;
@@ -14207,6 +14326,17 @@ ORDER BY SchemaName, TableName, TriggerName;";
1420714326
IsUniqueConstraint ? "true" : "false", IsClustered ? "true" : "false");
1420814327
}
1420914328
}
14329+
public class RawMemoryOptimisedTable
14330+
{
14331+
public readonly string SchemaName;
14332+
public readonly string TableName;
14333+
14334+
public RawMemoryOptimisedTable(string schemaName, string tableName)
14335+
{
14336+
SchemaName = schemaName;
14337+
TableName = tableName;
14338+
}
14339+
}
1421014340

1421114341
public class RawSequence
1421214342
{
@@ -14521,6 +14651,11 @@ SELECT * FROM MultiContext.ForeignKey;";
1452114651
return string.Empty;
1452214652
}
1452314653

14654+
protected override string[] MemoryOptimisedSQL()
14655+
{
14656+
return null;
14657+
}
14658+
1452414659
protected override string SynonymTableSQLSetup()
1452514660
{
1452614661
return string.Empty;
@@ -15065,6 +15200,16 @@ WHERE T.type = 'TR'
1506515200
ORDER BY SchemaName, TableName, TriggerName;";
1506615201
}
1506715202

15203+
protected override string[] MemoryOptimisedSQL()
15204+
{
15205+
return new string[]
15206+
{
15207+
"SELECT compatibility_level FROM sys.databases WHERE name = DB_NAME();",
15208+
"SELECT CAST(SERVERPROPERTY(N'IsXTPSupported') AS BIT) AS IsXTPSupported;",
15209+
"SELECT SCHEMA_NAME(schema_id) SchemaName, name TableName FROM sys.tables WHERE is_memory_optimized = 1;"
15210+
};
15211+
}
15212+
1506815213
protected override string SynonymTableSQLSetup()
1506915214
{
1507015215
return @"
@@ -16145,12 +16290,14 @@ SELECT SERVERPROPERTY('Edition') AS Edition,
1614516290
public bool UsesDictionary;
1614616291
public bool HasPrimaryKey;
1614716292
public bool RemoveTable;
16293+
public bool IsMemoryOptimised;
1614816294
public string AdditionalComment;
1614916295
public string PluralNameOverride;
1615016296
public string DbSetModifier = "public";
1615116297
public string BaseClasses;
1615216298
public string TriggerName;
1615316299

16300+
1615416301
public List<Column> Columns;
1615516302
public List<PropertyAndComments> ReverseNavigationProperty;
1615616303
public List<string> MappingConfiguration;
@@ -16575,6 +16722,8 @@ SELECT SERVERPROPERTY('Edition') AS Edition,
1657516722
public bool UseLazyLoadingProxies { get; set; }
1657616723
public bool hasTriggers { get; set; }
1657716724
public List<Trigger> Triggers { get; set; }
16725+
public bool hasMemoryOptimisedTables { get; set; }
16726+
public List<string> MemoryOptimisedTables { get; set; }
1657816727
}
1657916728
public class FactoryModel
1658016729
{
@@ -23075,6 +23224,13 @@ using {{this}};{{#newline}}
2307523224
{{/each}}
2307623225
{{/if}}
2307723226

23227+
{{#if hasMemoryOptimisedTables}}
23228+
{{#newline}}
23229+
{{#each MemoryOptimisedTables}}
23230+
modelBuilder.Entity<{{this}}>().IsMemoryOptimized();{{#newline}}
23231+
{{/each}}
23232+
{{/if}}
23233+
2307823234
{{#if hasStoredProcs}}
2307923235
{{#newline}}
2308023236
{{#each storedProcs}}
@@ -24694,6 +24850,13 @@ using {{this}};{{#newline}}
2469424850
{{/each}}
2469524851
{{/if}}
2469624852

24853+
{{#if hasMemoryOptimisedTables}}
24854+
{{#newline}}
24855+
{{#each MemoryOptimisedTables}}
24856+
modelBuilder.Entity<{{this}}>().IsMemoryOptimized();{{#newline}}
24857+
{{/each}}
24858+
{{/if}}
24859+
2469724860
{{#if hasTriggers}}
2469824861
{{#newline}}
2469924862
{{#each Triggers}}

Generator.Tests.Unit/FakeDatabaseReader.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ protected override string TriggerSQL()
7272
return string.Empty;
7373
}
7474

75+
protected override string[] MemoryOptimisedSQL()
76+
{
77+
return null;
78+
}
79+
7580
protected override string SynonymTableSQLSetup()
7681
{
7782
return string.Empty;

Generator/Generator.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
<Compile Include="LanguageMapping\IDatabaseToPropertyType.cs" />
106106
<Compile Include="OnConfiguration.cs" />
107107
<Compile Include="Readers\MinMaxValueCache.cs" />
108+
<Compile Include="Readers\RawMemoryOptimisedTable.cs" />
108109
<Compile Include="Readers\RawSequence.cs" />
109110
<Compile Include="Readers\RawTrigger.cs" />
110111
<Compile Include="TemplateModels\Trigger.cs" />

Generator/Generators/CodeGenerator.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -342,12 +342,14 @@ public CodeOutput GenerateContext()
342342
UseLazyLoadingProxies = Settings.UseLazyLoading && Settings.IsEfCore3Plus(),
343343
SqlParameter = Settings.SqlParameter(),
344344
Triggers = _tables.Where(x => !string.IsNullOrEmpty(x.Table.TriggerName))
345-
.Select(x => new Trigger { TableName = x.Table.NameHumanCase, TriggerName = x.Table.TriggerName }).ToList()
345+
.Select(x => new Trigger { TableName = x.Table.NameHumanCase, TriggerName = x.Table.TriggerName }).ToList(),
346+
MemoryOptimisedTables = _tables.Where(x => x.Table.IsMemoryOptimised).Select(x => x.Table.NameHumanCase).ToList()
346347
};
347348

348-
data.hasIndexes = data.indexes.Any();
349-
data.hasTriggers = data.Triggers.Any();
350-
data.hasSequences = data.Sequences.Any();
349+
data.hasIndexes = data.indexes.Any();
350+
data.hasTriggers = data.Triggers.Any();
351+
data.hasSequences = data.Sequences.Any();
352+
data.hasMemoryOptimisedTables = data.MemoryOptimisedTables.Any();
351353

352354
var co = new CodeOutput(string.Empty, filename, "Database context", Settings.ContextFolder, _globalUsings);
353355
co.AddUsings(_template.DatabaseContextUsings(data));

Generator/Generators/Generator.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,12 @@ public void LoadTables()
270270
AddIndexesToFilters(rawIndexes);
271271
SetPrimaryKeys();
272272
AddForeignKeysToFilters(rawForeignKeys);
273+
274+
if (Settings.IsEfCore6Plus())
275+
{
276+
var rawMemoryOptimisedTables = DatabaseReader.ReadMemoryOptimisedTables();
277+
AddMemoryOptimisedTablesToFilters(rawMemoryOptimisedTables);
278+
}
273279

274280
if (Settings.IsEfCore7Plus())
275281
{
@@ -633,6 +639,30 @@ private void AddTriggersToFilters(List<RawTrigger> triggers)
633639
}
634640
}
635641

642+
private void AddMemoryOptimisedTablesToFilters(List<RawMemoryOptimisedTable> memoryOptimisedTables)
643+
{
644+
if (memoryOptimisedTables == null || !memoryOptimisedTables.Any())
645+
return;
646+
647+
foreach (var filterKeyValuePair in FilterList.GetFilters())
648+
{
649+
var filter = filterKeyValuePair.Value;
650+
651+
Table t = null;
652+
foreach (var trigger in memoryOptimisedTables)
653+
{
654+
// Lookup table
655+
if (t == null || t.DbName != trigger.TableName || t.Schema.DbName != trigger.SchemaName)
656+
t = filter.Tables.GetTable(trigger.TableName, trigger.SchemaName);
657+
658+
if (t == null)
659+
continue;
660+
661+
t.IsMemoryOptimised = true;
662+
}
663+
}
664+
}
665+
636666
private void AddExtendedPropertiesToFilters(List<RawExtendedProperty> extendedProperties)
637667
{
638668
if (extendedProperties == null || !extendedProperties.Any())

0 commit comments

Comments
 (0)