Commit 6e49817d authored by Michael Herndon's avatar Michael Herndon

PROTO: EfCore.Relational update to use with version 3.0.1 of...

PROTO: EfCore.Relational update to use with version 3.0.1 of EntityFrameworkCore, which has breaking changes.
parent 8f861194
......@@ -105,14 +105,8 @@ public class NerdyMishkaOptionsExtension : IDbContextOptionsExtension
}
}
public DbContextOptionsExtensionInfo Info => throw new NotImplementedException();
public bool ApplyServices(IServiceCollection services)
{
return true;
}
public long GetServiceProviderHashCode()
{
......@@ -164,4 +158,9 @@ public class NerdyMishkaOptionsExtension : IDbContextOptionsExtension
return extensions[0];
}
public void ApplyServices(IServiceCollection services)
{
}
}
\ No newline at end of file
......@@ -3,19 +3,21 @@ using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using NerdyMishka.ComponentModel.DataAnnotations;
using NerdyMishka.EfCore.Storage.ValueConversion;
using NerdyMishka.Flex;
using NerdyMishka.Security.Cryptography;
namespace NerdyMishka.EfCore.Metadata
{
public class EncryptPropertyConvention : IPropertyConvention
{
private IFlexCryptoProvider cryptoProvider;
private IFlexHashProvider hashProvider;
public EncryptPropertyConvention(IFlexCryptoProvider cryptoProvider, IFlexHashProvider hashProvider)
private IHashProvider hashProvider;
public EncryptPropertyConvention(
ISymmetricEncryptionProvider provider,
IHashProvider hashProvider)
{
this.cryptoProvider = cryptoProvider;
ValueEncryptionProvider.EncryptionProvider = provider;
this.hashProvider = hashProvider;
}
......@@ -27,12 +29,12 @@ namespace NerdyMishka.EfCore.Metadata
bool unsupported = true;
var pt = mutableProperty.PropertyInfo.PropertyType;
if(pt == typeof(string)) {
mutableProperty.SetValueConverter(new EncryptedStringConverter(cryptoProvider));
mutableProperty.SetValueConverter(new StringEncryptionConverter());
unsupported = false;
}
if(pt == typeof(byte[])) {
mutableProperty.SetValueConverter(new EncryptedBinaryConverter(cryptoProvider));
mutableProperty.SetValueConverter(new ByteEncryptionConverter());
unsupported = false;
}
......@@ -46,7 +48,7 @@ namespace NerdyMishka.EfCore.Metadata
var pt = mutableProperty.PropertyInfo.PropertyType;
if(pt == typeof(String)) {
mutableProperty.SetValueConverter(new HashStringConverter(hashProvider));
mutableProperty.SetValueConverter(new HashStringConverter(this.hashProvider));
unsupported = false;
}
......
......@@ -15,7 +15,7 @@ namespace NerdyMishka.EfCore.Metadata
public interface IRelationalEntityTypeConvention : IEfCoreConvention
{
void Apply(RelationalEntityTypeAnnotations annotations);
void Apply(IMutableEntityType annotations);
}
public interface IPropertyConvention : IEfCoreConvention
......@@ -25,7 +25,7 @@ namespace NerdyMishka.EfCore.Metadata
public interface IRelationalPropertyConvention : IEfCoreConvention
{
void Apply(RelationalPropertyAnnotations annotations);
void Apply(IMutableProperty annotations);
}
public interface IForeignKeyConvention : IEfCoreConvention
......@@ -35,7 +35,7 @@ namespace NerdyMishka.EfCore.Metadata
public interface IRelationalForeignKeyConvention : IEfCoreConvention
{
void Apply(RelationalForeignKeyAnnotations annotations);
void Apply(IMutableForeignKey annotations);
}
public interface IKeyConvention : IEfCoreConvention
......@@ -45,7 +45,7 @@ namespace NerdyMishka.EfCore.Metadata
public interface IRelationalKeyConvention : IEfCoreConvention
{
void Apply(RelationalKeyAnnotations annotations);
void Apply(IMutableKey annotations);
}
public interface IIndexConvention : IEfCoreConvention
......@@ -55,7 +55,7 @@ namespace NerdyMishka.EfCore.Metadata
public interface IRelationalIndexConvention: IEfCoreConvention
{
void Apply(RelationalIndexAnnotations annotations);
void Apply(IMutableIndex annotations);
}
public interface INavigationConvention: IEfCoreConvention
......
......@@ -111,7 +111,7 @@ namespace NerdyMishka.EfCore.Metadata
}
if(relationalEntityTypeConventions.Count > 0) {
var annotations = entityType.Relational();
var annotations = entityType;
foreach(var c in relationalEntityTypeConventions)
c.Apply(annotations);
}
......@@ -128,7 +128,7 @@ namespace NerdyMishka.EfCore.Metadata
}
if(relationalEntityTypeConventions.Count > 0) {
var annotation = property.Relational();
var annotation = property;
foreach(var c in relationalPropertyConventions)
c.Apply(annotation);
}
......@@ -148,7 +148,7 @@ namespace NerdyMishka.EfCore.Metadata
if(relationalKeyConventions.Count > 0)
{
var annotation = key.Relational();
var annotation = key;
foreach(var c in relationalKeyConventions)
c.Apply(annotation);
}
......@@ -168,7 +168,7 @@ namespace NerdyMishka.EfCore.Metadata
if(relationalIndexConventions.Count > 0)
{
var annotation = ix.Relational();
var annotation = ix;
foreach(var c in relationalIndexConventions)
c.Apply(annotation);
}
......@@ -193,7 +193,7 @@ namespace NerdyMishka.EfCore.Metadata
if(relationalFkConventions.Count > 0)
{
var annotation = fk.Relational();
var annotation = fk;
foreach(var c in relationalFkConventions)
c.Apply(annotation);
}
......@@ -212,7 +212,8 @@ namespace NerdyMishka.EfCore.Metadata
}
}
var sequences = builder.Model.Relational()?.Sequences;
var sequences = builder.Model.GetSequences();
if(sequences != null && sequences.Count > 0)
{
foreach(var s in sequences)
......
......@@ -35,13 +35,14 @@ namespace NerdyMishka.EfCore.Metadata
this.conventions = conventions;
}
public void Apply(RelationalEntityTypeAnnotations annotations)
public void Apply(IMutableEntityType annotations)
{
annotations.TableName = conventions.FormatTableName(annotations.TableName);
annotations.SetTableName(conventions.FormatTableName(annotations.GetTableName()));
if(!string.IsNullOrWhiteSpace(annotations.Schema))
annotations.Schema = conventions.FormatSchemaName(annotations.Schema);
var schema = annotations.GetSchema();
if(!string.IsNullOrWhiteSpace(schema))
annotations.SetSchema(conventions.FormatSchemaName(schema));
}
}
......@@ -52,9 +53,14 @@ namespace NerdyMishka.EfCore.Metadata
{
this.conventions = conventions;
}
public void Apply(RelationalPropertyAnnotations annotations)
public void Apply(IMutableProperty annotations)
{
annotations.ColumnName = this.conventions.FormatColumnName(annotations.ColumnName);
var columnName = this.conventions.FormatColumnName(
annotations.GetColumnName());
annotations.SetColumnName(columnName);
}
}
......@@ -67,8 +73,7 @@ namespace NerdyMishka.EfCore.Metadata
}
public void Apply(IMutableIndex index)
{
var r = index.Relational();
r.Name = conventions.GetDefaultName(index);
index.SetName(conventions.GetDefaultName(index));
}
}
......@@ -81,8 +86,7 @@ namespace NerdyMishka.EfCore.Metadata
}
public void Apply(IMutableForeignKey fk)
{
var r = fk.Relational();
r.Name = conventions.GetDefaultName(fk);
fk.SetConstraintName(conventions.GetDefaultName(fk));
}
}
......@@ -95,8 +99,7 @@ namespace NerdyMishka.EfCore.Metadata
}
public void Apply(IMutableKey key)
{
var r = key.Relational();
r.Name = conventions.GetDefaultName(key);
key.SetName(conventions.GetDefaultName(key));
}
}
......@@ -137,16 +140,16 @@ namespace NerdyMishka.EfCore.Metadata
public string GetDefaultTableName(IEntityType entityType)
{
return FormatTableName(entityType.Relational().TableName);
return FormatTableName(entityType.GetTableName());
}
public string GetDefaultSchemaName(IEntityType entityType)
{
var s = entityType.Relational().Schema;
var s = entityType.GetSchema();
if(s == null)
return s;
return FormatSchemaName(entityType.Relational().Schema);
return FormatSchemaName(entityType.GetSchema());
}
......@@ -158,11 +161,11 @@ namespace NerdyMishka.EfCore.Metadata
{
var baseName = new StringBuilder()
.Append(ForeignKeyPrefix)
.Append(foreignKey.DeclaringEntityType.Relational().TableName)
.Append(foreignKey.DeclaringEntityType.GetTableName())
.Append("__")
.Append(foreignKey.PrincipalEntityType.Relational().TableName)
.Append(foreignKey.PrincipalEntityType.GetTableName())
.Append("__")
.AppendJoin(foreignKey.Properties.Select(p => p.Relational().ColumnName), "__")
.AppendJoin(foreignKey.Properties.Select(p => p.GetColumnName()), "__")
.ToString();
return Truncate(baseName, null, foreignKey.DeclaringEntityType.Model.GetMaxIdentifierLength());
......@@ -176,9 +179,9 @@ namespace NerdyMishka.EfCore.Metadata
{
var baseName = new StringBuilder()
.Append(IndexPrefix)
.Append(index.DeclaringEntityType.Relational().TableName)
.Append(index.DeclaringEntityType.GetTableName())
.Append("__")
.AppendJoin(index.Properties.Select(p => p.Relational().ColumnName), "__")
.AppendJoin(index.Properties.Select(p => p.GetColumnName()), "__")
.ToString();
return Truncate(baseName, null, index.DeclaringEntityType.Model.GetMaxIdentifierLength());
......@@ -193,11 +196,13 @@ namespace NerdyMishka.EfCore.Metadata
var sharedTablePrincipalPrimaryKeyProperty = key.Properties[0].FindSharedTableRootPrimaryKeyProperty();
if (sharedTablePrincipalPrimaryKeyProperty != null)
{
return sharedTablePrincipalPrimaryKeyProperty.GetContainingPrimaryKey().Relational().Name;
return sharedTablePrincipalPrimaryKeyProperty
.FindContainingPrimaryKey()
.GetDefaultName();
}
var builder = new StringBuilder();
var tableName = key.DeclaringEntityType.Relational().TableName;
var tableName = key.DeclaringEntityType.GetTableName();
if (key.IsPrimaryKey())
{
......@@ -211,7 +216,7 @@ namespace NerdyMishka.EfCore.Metadata
.Append(AlternateKeyPrefix)
.Append(tableName)
.Append("_")
.AppendJoin(key.Properties.Select(p => p.Relational().ColumnName), "__");
.AppendJoin(key.Properties.Select(p => p.GetColumnName()), "__");
}
return Truncate(builder.ToString(), null, key.DeclaringEntityType.Model.GetMaxIdentifierLength());
......@@ -226,7 +231,7 @@ namespace NerdyMishka.EfCore.Metadata
var sharedTablePrincipalPrimaryKeyProperty = property.FindSharedTableRootPrimaryKeyProperty();
if (sharedTablePrincipalPrimaryKeyProperty != null)
{
return sharedTablePrincipalPrimaryKeyProperty.Relational().ColumnName;
return sharedTablePrincipalPrimaryKeyProperty.GetDefaultColumnName();
}
var entityType = property.DeclaringEntityType;
......@@ -240,11 +245,12 @@ namespace NerdyMishka.EfCore.Metadata
}
else
{
var ownerType = ownership.PrincipalEntityType;
var entityTypeAnnotations = entityType.Relational();
var ownerTypeAnnotations = ownerType.Relational();
if (entityTypeAnnotations.TableName == ownerTypeAnnotations.TableName
&& entityTypeAnnotations.Schema == ownerTypeAnnotations.Schema)
var entityTypeAnnotations = entityType;
var ownerTypeAnnotations = ownerType;
if (entityTypeAnnotations.GetTableName() == ownerTypeAnnotations.GetTableName()
&& entityTypeAnnotations.GetSchema() == ownerTypeAnnotations.GetSchema())
{
if (builder == null)
{
......
......@@ -14,7 +14,8 @@ namespace NerdyMishka.EfCore.Metadata
this EntityTypeBuilder<TModel> builder,
string schemaName
) where TModel: class {
builder.Metadata.Relational().Schema = schemaName;
builder.Metadata.SetSchema(schemaName);
return builder;
}
......
......@@ -45,7 +45,7 @@ namespace NerdyMishka.EfCore.Migrations
Sqlite,
SqlServer,
MySql,
Postgres
PostgreSql
}
public NerdyMishkaHistoryRepository(HistoryRepositoryDependencies dependencies) : base(dependencies)
......@@ -83,7 +83,7 @@ namespace NerdyMishka.EfCore.Migrations
{
get
{
var stringTypeMapping = Dependencies.TypeMappingSource.GetMapping(typeof(string));
var stringTypeMapping = Dependencies.TypeMappingSource.GetMapping(typeof(string));
switch(this.dbType)
{
case RelationalDbTypes.SqlServer:
......
......@@ -4,17 +4,13 @@
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="2.2.4" />
<PackageReference Include="Humanizer.Core" Version="2.6.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.0" />
<PackageReference Include="Humanizer.Core" Version="2.7.9" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../Flex/NerdyMishka.Flex.csproj" />
<ItemGroup>
<ProjectReference Include="../../Bcl/Proto/*.csproj" />
</ItemGroup>
</Project>
using System;
using System.Linq.Expressions;
using JetBrains.Annotations;
using NerdyMishka.Flex;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace NerdyMishka.EfCore.Storage.ValueConversion
{
public class EncryptedBinaryConverter : ValueConverter<byte[], byte[]>
{
public EncryptedBinaryConverter(
IFlexCryptoProvider provider
) : base(
v => provider.EncryptBlob(v, null),
v => provider.DecryptBlob(v, null))
{
}
}
}
\ No newline at end of file
using System;
using System.Linq.Expressions;
using JetBrains.Annotations;
using NerdyMishka.Flex;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace NerdyMishka.EfCore.Storage.ValueConversion
{
public class EncryptedStringConverter : ValueConverter<string, string>
{
public EncryptedStringConverter(
IFlexCryptoProvider provider
) : base(
v => provider.EncryptString(v, null),
v => provider.DecryptString(v, null))
{
}
}
}
\ No newline at end of file
using System;
using System.Linq;
using System.Linq.Expressions;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using NerdyMishka.Security.Cryptography;
using System.Text;
using System.Security;
namespace NerdyMishka.EfCore.Storage.ValueConversion
{
public class SecureStringEncryptionConverter : ValueEncryptionConverter<SecureString, string>
{
public SecureStringEncryptionConverter()
:base(
(to) => ValueEncryptionProvider.EncryptString(to),
(from) =>ValueEncryptionProvider.DecryptSecureString(from))
{
}
}
public class StringEncryptionConverter : ValueEncryptionConverter<string, string>
{
public StringEncryptionConverter(
) : base(
(to) => ValueEncryptionProvider.EncryptString(to),
(from) => ValueEncryptionProvider.DecryptString(from)
)
{
}
}
public class StringToBytesEncryptionConverter : ValueEncryptionConverter<string, byte[]>
{
public StringToBytesEncryptionConverter(
) : base(
(to) => ValueEncryptionProvider.Encrypt(to),
(from) => ValueEncryptionProvider.DecryptString(from))
{
}
}
public class BytesToStringEncryptionConverter : ValueEncryptionConverter<byte[], string>
{
public BytesToStringEncryptionConverter(
) : base((to) => ValueEncryptionProvider.EncryptString(to),
(from) => ValueEncryptionProvider.Decrypt(from))
{
}
}
public class ByteEncryptionConverter : ValueEncryptionConverter<byte[], byte[]>
{
public ByteEncryptionConverter() : base(
(to) => ValueEncryptionProvider.Encrypt(to),
(from) => ValueEncryptionProvider.Decrypt(from),
null
)
{
}
}
public static class ValueEncryptionProvider
{
public static ISymmetricEncryptionProvider EncryptionProvider { get; set; }
public static string EncryptString(SecureString ss)
{
var bytes = ss.ToBytes();
return EncryptString(bytes);
}
public static string EncryptString(byte[] value)
{
return Convert.ToBase64String(
Encrypt(value));
}
public static string EncryptString(string value)
{
return Convert.ToBase64String(
Encrypt(value));
}
public static byte[] Encrypt(byte[] value)
{
return EncryptionProvider.Encrypt(value);
}
public static byte[] Encrypt(string value)
{
var bytes = NerdyMishka.Text.Encodings.Utf8NoBom.GetBytes(value);
return EncryptionProvider.Encrypt(bytes);
}
public static SecureString DecryptSecureString(string value)
{
var bytes = Decrypt(value);
var chars = NerdyMishka.Text.Encodings.Utf8NoBom.GetChars(bytes);
var ss = new SecureString();
foreach(var c in chars)
ss.AppendChar(c);
chars.Clear();
bytes.Clear();
return ss;
}
public static string DecryptString(string value)
{
var bytes = Decrypt(value);
return NerdyMishka.Text.Encodings.Utf8NoBom.GetString(bytes);
}
public static string DecryptString(byte[] value)
{
var bytes = Decrypt(value);
return NerdyMishka.Text.Encodings.Utf8NoBom.GetString(bytes);
}
public static byte[] Decrypt(byte[] value)
{
return EncryptionProvider.Decrypt(value);
}
public static byte[] Decrypt(string value)
{
var bytes = System.Convert.FromBase64String(value);
return EncryptionProvider.Decrypt(bytes);
}
}
public abstract class ValueEncryptionConverter<TFrom, TTo> : ValueConverter<TFrom, TTo>
{
public static ISymmetricEncryptionProvider EncryptionProvider { get; set; }
static ValueEncryptionConverter()
{
var key = NerdyMishka.Text.Encodings.Utf8NoBom.GetBytes("!@#dfa2-0daa 2 daax23 xwcxXcwe2");
ValueEncryptionProvider.EncryptionProvider = new SymmetricEncryptionProvider(new SymmetricEncryptionProviderOptions(){
Key = key,
Iterations = 20000
});
}
public ValueEncryptionConverter(
Expression<Func<TFrom, TTo>> convertToProviderExpression,
Expression<Func<TTo, TFrom>> convertFromProviderExpression,
ConverterMappingHints mappingHints = null) : base(convertToProviderExpression, convertFromProviderExpression, mappingHints)
{
}
}
}
\ No newline at end of file
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using NerdyMishka.Flex;
using NerdyMishka.Security.Cryptography;
namespace EfCore.Relational.Storage.ValueConversion
{
public class HashBinaryConverter : ValueConverter<byte[], byte[]>
{
public HashBinaryConverter(
IFlexHashProvider provider, int iterations = 64000
IHashProvider provider
) : base(
v => provider.ComputeHash(v, iterations),
v => provider.ComputeHash(v, iterations))
v => provider.ComputeHash(v),
v => v)
{
}
......
using System;
using System.Linq.Expressions;
using JetBrains.Annotations;
using NerdyMishka.Flex;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using NerdyMishka.Security.Cryptography;
namespace NerdyMishka.EfCore.Storage.ValueConversion
{
......@@ -11,12 +9,14 @@ namespace NerdyMishka.EfCore.Storage.ValueConversion
public class HashCharacterConverter : ValueConverter<char[], char[]>
{
public HashCharacterConverter(
IFlexHashProvider provider, int iterations = 64000
IHashProvider provider
) : base(
v => provider.ComputeHash(v, iterations),
v => provider.ComputeHash(v, iterations))
v => Convert.ToBase64String(
provider.ComputeHash(NerdyMishka.Text.Encodings.Utf8NoBom.GetBytes(v)))
.ToCharArray(),
v => v)
{
}
}
}
\ No newline at end of file
using System;
using System.Linq.Expressions;
using JetBrains.Annotations;
using NerdyMishka.Flex;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using NerdyMishka.Security.Cryptography;
namespace NerdyMishka.EfCore.Storage.ValueConversion
{
......@@ -11,10 +9,12 @@ namespace NerdyMishka.EfCore.Storage.ValueConversion
public class HashStringConverter : ValueConverter<string, string>
{
public HashStringConverter(
IFlexHashProvider provider, int iterations = 64000
IHashProvider provider
) : base(
v => provider.ComputeHash(v, iterations),
v => provider.ComputeHash(v, iterations))
v =>
Convert.ToBase64String(