2
0
mirror of https://github.com/esiur/esiur-dotnet.git synced 2025-09-13 12:43:17 +00:00

.Net 6 Upgrade

This commit is contained in:
2021-12-01 12:17:45 +03:00
parent 1166e93ba9
commit 530df018ec
164 changed files with 21247 additions and 21425 deletions

View File

@@ -32,44 +32,42 @@ using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace Esiur.Stores.EntityCore
namespace Esiur.Stores.EntityCore;
public class EntityResource : IResource
{
public class EntityResource : IResource
//[NotMapped]
//internal object _PrimaryId;
public event DestroyedEvent OnDestroy;
//public event PropertyChangedEventHandler PropertyChanged;
[NotMapped]
public Instance Instance { get; set; }
public EntityResource()
{
//[NotMapped]
//internal object _PrimaryId;
public event DestroyedEvent OnDestroy;
//public event PropertyChangedEventHandler PropertyChanged;
[NotMapped]
public Instance Instance { get; set; }
public EntityResource()
{
}
protected virtual void Create()
{
}
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
if (trigger == ResourceTrigger.Initialize)
Create();
return new AsyncReply<bool>(true);
}
public void Destroy()
{
OnDestroy?.Invoke(this);
}
}
protected virtual void Create()
{
}
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
if (trigger == ResourceTrigger.Initialize)
Create();
return new AsyncReply<bool>(true);
}
public void Destroy()
{
OnDestroy?.Invoke(this);
}
}

View File

@@ -34,209 +34,207 @@ using System.Linq;
using Microsoft.EntityFrameworkCore.Metadata;
using System.Reflection;
namespace Esiur.Stores.EntityCore
namespace Esiur.Stores.EntityCore;
public class EntityStore : IStore
{
public class EntityStore : IStore
public Instance Instance { get; set; }
public event DestroyedEvent OnDestroy;
Dictionary<Type, Dictionary<object, WeakReference>> DB = new Dictionary<Type, Dictionary<object, WeakReference>>();
object DBLock = new object();
Dictionary<string, EntityTypeInfo> TypesByName = new Dictionary<string, EntityTypeInfo>();
internal Dictionary<Type, EntityTypeInfo> TypesByType = new Dictionary<Type, EntityTypeInfo>();
[Attribute]
public Func<DbContext> Getter { get; set; }
public AsyncReply<IResource> Get(string path)
{
public Instance Instance { get; set; }
var p = path.Split('/');
var ti = TypesByName[p[0]];
var id = Convert.ChangeType(p[1], ti.PrimaryKey.PropertyType);
public event DestroyedEvent OnDestroy;
// Get db
var db = Getter();
var res = db.Find(ti.Type.ClrType, id);
Dictionary<Type, Dictionary<object, WeakReference>> DB = new Dictionary<Type, Dictionary<object, WeakReference>>();
object DBLock = new object();
// load navigation properties
var ent = db.Entry(res);
foreach (var rf in ent.References)
rf.Load();
Dictionary<string, EntityTypeInfo> TypesByName = new Dictionary<string, EntityTypeInfo>();
internal Dictionary<Type, EntityTypeInfo> TypesByType = new Dictionary<Type, EntityTypeInfo>();
[Attribute]
public Func<DbContext> Getter { get; set; }
public AsyncReply<IResource> Get(string path)
{
var p = path.Split('/');
var ti = TypesByName[p[0]];
var id = Convert.ChangeType(p[1], ti.PrimaryKey.PropertyType);
// Get db
var db = Getter();
var res = db.Find(ti.Type.ClrType, id);
// load navigation properties
var ent = db.Entry(res);
foreach (var rf in ent.References)
rf.Load();
return new AsyncReply<IResource>(res as IResource);
}
public AsyncReply<bool> Put(IResource resource)
{
if (resource == this)
return new AsyncReply<bool>(true);
var type = ResourceProxy.GetBaseType(resource);
var eid = TypesByType[type].PrimaryKey.GetValue(resource);
lock (DBLock)
{
if (DB[type].ContainsKey(eid))
DB[type].Remove(eid);
DB[type].Add(eid, new WeakReference(resource));
}
return new AsyncReply<IResource>(res as IResource);
}
public AsyncReply<bool> Put(IResource resource)
{
if (resource == this)
return new AsyncReply<bool>(true);
var type = ResourceProxy.GetBaseType(resource);
var eid = TypesByType[type].PrimaryKey.GetValue(resource);
lock (DBLock)
{
if (DB[type].ContainsKey(eid))
DB[type].Remove(eid);
DB[type].Add(eid, new WeakReference(resource));
}
public IResource GetById(Type type, object id)
return new AsyncReply<bool>(true);
}
public IResource GetById(Type type, object id)
{
lock (DBLock)
{
lock (DBLock)
{
if (!DB[type].ContainsKey(id))
return null;
if (!DB[type].ContainsKey(id))
return null;
if (!DB[type][id].IsAlive)
return null;
if (!DB[type][id].IsAlive)
return null;
return DB[type][id].Target as IResource;
}
}
//public T CreateDB()
//{
//}
//DbContext dbContext;
//[Attribute]
//public DbContext DbContext { get; set; }
public string Link(IResource resource)
{
var type = ResourceProxy.GetBaseType(resource.GetType());
var id = TypesByType[type].PrimaryKey.GetValue(resource);
//DbContext.Model.FindEntityType(type).DisplayName();
// DbContext.Model.FindEntityType(type).DisplayName
//var entityType = DbContext.Model.FindEntityType(type);
//var id = entityType.FindPrimaryKey().Properties
// .FirstOrDefault()?.PropertyInfo
// .GetValue(resource);
// var id = Types
if (id != null)
return this.Instance.Name + "/" + type.Name + "/" + id.ToString();
else
return this.Instance.Name + "/" + type.Name;
}
public bool Record(IResource resource, string propertyName, object value, ulong age, DateTime dateTime)
{
return true;
//throw new NotImplementedException();
}
public bool Modify(IResource resource, string propertyName, object value, ulong age, DateTime dateTime)
{
return true;
//throw new NotImplementedException();
}
public bool Remove(IResource resource)
{
throw new NotImplementedException();
}
public AsyncReply<bool> AddChild(IResource parent, IResource child)
{
throw new NotImplementedException();
}
public AsyncReply<bool> RemoveChild(IResource parent, IResource child)
{
throw new NotImplementedException();
}
public AsyncReply<bool> AddParent(IResource child, IResource parent)
{
throw new NotImplementedException();
}
public AsyncReply<bool> RemoveParent(IResource child, IResource parent)
{
throw new NotImplementedException();
}
public AsyncBag<T> Children<T>(IResource resource, string name) where T : IResource
{
throw new NotImplementedException();
}
public AsyncBag<T> Parents<T>(IResource resource, string name) where T : IResource
{
throw new NotImplementedException();
}
public AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>> GetRecord(IResource resource, DateTime fromDate, DateTime toDate)
{
throw new NotImplementedException();
}
internal DbContextOptions Options { get; set; }
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
if (trigger == ResourceTrigger.Initialize)// SystemInitialized && DbContext != null)
{
if (Getter == null)
throw new Exception("Getter is not set for the store.");
// DbContextProvider = () => Activator.CreateInstance(Options.Options.ContextType, Options.Options) as DbContext;
ReloadModel();
}
return new AsyncReply<bool>(true);
}
public void ReloadModel()
{
TypesByName.Clear();
TypesByType.Clear();
var context = Getter();
var types = context.Model.GetEntityTypes();
foreach (var t in types)
{
var ti = new EntityTypeInfo()
{
Name = t.ClrType.Name,
PrimaryKey = t.FindPrimaryKey().Properties.FirstOrDefault()?.PropertyInfo,
Type = t,
//Getter = getter
};
TypesByName.Add(t.ClrType.Name, ti);
TypesByType.Add(t.ClrType, ti);
if (!DB.ContainsKey(t.ClrType))
DB.Add(t.ClrType, new Dictionary<object, WeakReference>());
}
}
public void Destroy()
{
OnDestroy?.Invoke(this);
return DB[type][id].Target as IResource;
}
}
//public T CreateDB()
//{
//}
//DbContext dbContext;
//[Attribute]
//public DbContext DbContext { get; set; }
public string Link(IResource resource)
{
var type = ResourceProxy.GetBaseType(resource.GetType());
var id = TypesByType[type].PrimaryKey.GetValue(resource);
//DbContext.Model.FindEntityType(type).DisplayName();
// DbContext.Model.FindEntityType(type).DisplayName
//var entityType = DbContext.Model.FindEntityType(type);
//var id = entityType.FindPrimaryKey().Properties
// .FirstOrDefault()?.PropertyInfo
// .GetValue(resource);
// var id = Types
if (id != null)
return this.Instance.Name + "/" + type.Name + "/" + id.ToString();
else
return this.Instance.Name + "/" + type.Name;
}
public bool Record(IResource resource, string propertyName, object value, ulong age, DateTime dateTime)
{
return true;
//throw new NotImplementedException();
}
public bool Modify(IResource resource, string propertyName, object value, ulong age, DateTime dateTime)
{
return true;
//throw new NotImplementedException();
}
public bool Remove(IResource resource)
{
throw new NotImplementedException();
}
public AsyncReply<bool> AddChild(IResource parent, IResource child)
{
throw new NotImplementedException();
}
public AsyncReply<bool> RemoveChild(IResource parent, IResource child)
{
throw new NotImplementedException();
}
public AsyncReply<bool> AddParent(IResource child, IResource parent)
{
throw new NotImplementedException();
}
public AsyncReply<bool> RemoveParent(IResource child, IResource parent)
{
throw new NotImplementedException();
}
public AsyncBag<T> Children<T>(IResource resource, string name) where T : IResource
{
throw new NotImplementedException();
}
public AsyncBag<T> Parents<T>(IResource resource, string name) where T : IResource
{
throw new NotImplementedException();
}
public AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>> GetRecord(IResource resource, DateTime fromDate, DateTime toDate)
{
throw new NotImplementedException();
}
internal DbContextOptions Options { get; set; }
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
if (trigger == ResourceTrigger.Initialize)// SystemInitialized && DbContext != null)
{
if (Getter == null)
throw new Exception("Getter is not set for the store.");
// DbContextProvider = () => Activator.CreateInstance(Options.Options.ContextType, Options.Options) as DbContext;
ReloadModel();
}
return new AsyncReply<bool>(true);
}
public void ReloadModel()
{
TypesByName.Clear();
TypesByType.Clear();
var context = Getter();
var types = context.Model.GetEntityTypes();
foreach (var t in types)
{
var ti = new EntityTypeInfo()
{
Name = t.ClrType.Name,
PrimaryKey = t.FindPrimaryKey().Properties.FirstOrDefault()?.PropertyInfo,
Type = t,
//Getter = getter
};
TypesByName.Add(t.ClrType.Name, ti);
TypesByType.Add(t.ClrType, ti);
if (!DB.ContainsKey(t.ClrType))
DB.Add(t.ClrType, new Dictionary<object, WeakReference>());
}
}
public void Destroy()
{
OnDestroy?.Invoke(this);
}
}

View File

@@ -5,13 +5,12 @@ using System.Collections.Generic;
using System.Reflection;
using System.Text;
namespace Esiur.Stores.EntityCore
namespace Esiur.Stores.EntityCore;
struct EntityTypeInfo
{
struct EntityTypeInfo
{
public string Name;
public IEntityType Type;
public PropertyInfo PrimaryKey;
// public Func<DbContext> Getter;
}
public string Name;
public IEntityType Type;
public PropertyInfo PrimaryKey;
// public Func<DbContext> Getter;
}

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<AssemblyName>Esiur.Stores.EntityCore</AssemblyName>
<Authors>Ahmed Kh. Zamil</Authors>
<Company>Esiur Foundation</Company>
@@ -10,6 +10,7 @@
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageId>Esiur.Stores.EntityCore</PackageId>
<Version>1.2.5</Version>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
@@ -21,7 +22,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.0" />
<PackageReference Include="System.Collections" Version="4.3.0" />
</ItemGroup>

View File

@@ -36,79 +36,83 @@ using System.Reflection;
using Esiur.Proxy;
using Microsoft.EntityFrameworkCore;
namespace Esiur.Stores.EntityCore
namespace Esiur.Stores.EntityCore;
public class EsiurExtensionOptions : IDbContextOptionsExtension
{
public class EsiurExtensionOptions : IDbContextOptionsExtension
//public Dictionary<Type, PropertyInfo> Cache { get; } = new Dictionary<Type, PropertyInfo>();
//public void AddType(IEntityType type)
//{
// if (!Cache.ContainsKey(type.ClrType))
// Cache.Add(type.ClrType, type.FindPrimaryKey().Properties[0].PropertyInfo);
//}
private DbContextOptionsExtensionInfo _info;
EntityStore _store;
public DbContextOptionsExtensionInfo Info => _info;
public EntityStore Store => _store;
public void ApplyServices(IServiceCollection services)
{
// services.AddEntityFrameworkProxies();
new EntityFrameworkServicesBuilder(services)
.TryAdd<IConventionSetPlugin, EsiurPlugin>();
}
public void Validate(IDbContextOptions options)
{
var internalServiceProvider = options.FindExtension<CoreOptionsExtension>()?.InternalServiceProvider;
if (internalServiceProvider != null)
{
var scope = internalServiceProvider.CreateScope();
var conventionPlugins = scope.ServiceProvider.GetService<IEnumerable<IConventionSetPlugin>>();
if (conventionPlugins?.Any(s => s is EsiurPlugin) == false)
{
throw new InvalidOperationException("");
}
}
}
public EsiurExtensionOptions(EntityStore store)
{
_info = new ExtensionInfo(this);
_store = store;
}
private sealed class ExtensionInfo : DbContextOptionsExtensionInfo
{
//public Dictionary<Type, PropertyInfo> Cache { get; } = new Dictionary<Type, PropertyInfo>();
//public void AddType(IEntityType type)
//{
// if (!Cache.ContainsKey(type.ClrType))
// Cache.Add(type.ClrType, type.FindPrimaryKey().Properties[0].PropertyInfo);
//}
private DbContextOptionsExtensionInfo _info;
EntityStore _store;
public DbContextOptionsExtensionInfo Info => _info;
public EntityStore Store => _store;
public void ApplyServices(IServiceCollection services)
public ExtensionInfo(IDbContextOptionsExtension extension)
: base(extension)
{
// services.AddEntityFrameworkProxies();
new EntityFrameworkServicesBuilder(services)
.TryAdd<IConventionSetPlugin, EsiurPlugin>();
}
public void Validate(IDbContextOptions options)
{
var internalServiceProvider = options.FindExtension<CoreOptionsExtension>()?.InternalServiceProvider;
if (internalServiceProvider != null)
{
var scope = internalServiceProvider.CreateScope();
var conventionPlugins = scope.ServiceProvider.GetService<IEnumerable<IConventionSetPlugin>>();
if (conventionPlugins?.Any(s => s is EsiurPlugin) == false)
{
throw new InvalidOperationException("");
}
}
}
private new EsiurExtensionOptions Extension
=> (EsiurExtensionOptions)base.Extension;
public EsiurExtensionOptions(EntityStore store)
{
_info = new ExtensionInfo(this);
_store = store;
}
public override bool IsDatabaseProvider => false;
public override string LogFragment => "Esiur";
private sealed class ExtensionInfo : DbContextOptionsExtensionInfo
public override int GetServiceProviderHashCode() => 2312;
public override void PopulateDebugInfo(IDictionary<string, string> debugInfo)
{
public ExtensionInfo(IDbContextOptionsExtension extension)
: base(extension)
{
}
private new EsiurExtensionOptions Extension
=> (EsiurExtensionOptions)base.Extension;
public override bool IsDatabaseProvider => false;
public override string LogFragment => "Esiur";
public override long GetServiceProviderHashCode() => 2312;
public override void PopulateDebugInfo(IDictionary<string, string> debugInfo)
{
}
}
public override bool ShouldUseSameServiceProvider(DbContextOptionsExtensionInfo other)
{
return true;
}
}
}

View File

@@ -37,74 +37,62 @@ using System.Linq;
using System.Reflection;
using System.Text;
namespace Esiur.Stores.EntityCore
namespace Esiur.Stores.EntityCore;
public static class EsiurExtensions
{
public static class EsiurExtensions
//public static T CreateResource<T>(this DbContext dbContext, object properties = null) where T:class,IResource
//{
// return dbContext.GetInfrastructure().CreateResource<T>(properties);
//}
public static T AddResource<T>(this DbSet<T> dbSet, T resource) where T : class, IResource
=> AddResourceAsync(dbSet, resource).Wait();
public static async AsyncReply<T> AddResourceAsync<T>(this DbSet<T> dbSet, T resource) where T : class, IResource
{
//public static T CreateResource<T>(this DbContext dbContext, object properties = null) where T:class,IResource
//{
// return dbContext.GetInfrastructure().CreateResource<T>(properties);
var store = dbSet.GetInfrastructure().GetService<IDbContextOptions>().FindExtension<EsiurExtensionOptions>().Store;
//}
public static T AddResource<T>(this DbSet<T> dbSet, T resource) where T : class, IResource
=> AddResourceAsync(dbSet, resource).Wait();
var manager = store.Instance.Managers.FirstOrDefault();// > 0 ? store.Instance.Managers.First() : null;
public static async AsyncReply<T> AddResourceAsync<T>(this DbSet<T> dbSet, T resource) where T : class, IResource
//var db = dbSet.GetService<ICurrentDbContext>().Context;
//var resource = dbSet.GetInfrastructure().CreateResource<T>(properties);
//var resource = Warehouse.New<T>("", options.Store, null, null, null, properties);
var resType = typeof(T);
var proxyType = ResourceProxy.GetProxy(resType);
IResource res;
if (proxyType == resType)
{
var store = dbSet.GetInfrastructure().GetService<IDbContextOptions>().FindExtension<EsiurExtensionOptions>().Store;
res = resource;
}
else
{
res = Activator.CreateInstance(proxyType) as IResource;
var ps = Structure.FromObject(resource);
var manager = store.Instance.Managers.FirstOrDefault();// > 0 ? store.Instance.Managers.First() : null;
//var db = dbSet.GetService<ICurrentDbContext>().Context;
//var resource = dbSet.GetInfrastructure().CreateResource<T>(properties);
//var resource = Warehouse.New<T>("", options.Store, null, null, null, properties);
var resType = typeof(T);
var proxyType = ResourceProxy.GetProxy(resType);
IResource res;
if (proxyType == resType)
foreach (var p in ps)
{
res = resource;
}
else
{
res = Activator.CreateInstance(proxyType) as IResource;
var ps = Structure.FromObject(resource);
foreach (var p in ps)
var mi = resType.GetMember(p.Key, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)
.FirstOrDefault();
if (mi != null)
{
var mi = resType.GetMember(p.Key, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)
.FirstOrDefault();
if (mi != null)
if (mi is PropertyInfo)
{
if (mi is PropertyInfo)
{
var pi = mi as PropertyInfo;
if (pi.CanWrite)
{
try
{
pi.SetValue(res, p.Value);
}
catch (Exception ex)
{
Global.Log(ex);
}
}
}
else if (mi is FieldInfo)
var pi = mi as PropertyInfo;
if (pi.CanWrite)
{
try
{
(mi as FieldInfo).SetValue(res, p.Value);
pi.SetValue(res, p.Value);
}
catch (Exception ex)
{
@@ -112,90 +100,101 @@ namespace Esiur.Stores.EntityCore
}
}
}
else if (mi is FieldInfo)
{
try
{
(mi as FieldInfo).SetValue(res, p.Value);
}
catch (Exception ex)
{
Global.Log(ex);
}
}
}
}
//await Warehouse.Put<T>("", null, null, null, null, properties);
var entity = dbSet.Add((T)res);
await entity.Context.SaveChangesAsync();
var id = store.TypesByType[typeof(T)].PrimaryKey.GetValue(resource);
await Warehouse.Put(id.ToString(), res, store, null, null, 0, manager);
return (T)res;
}
//public static async AsyncReply<T> CreateResourceAsync<T>(this IServiceProvider serviceProvider, T properties = null) where T : class, IResource
//{
// var options = serviceProvider.GetService<IDbContextOptions>().FindExtension<EsiurExtensionOptions<T>>();
//await Warehouse.Put<T>("", null, null, null, null, properties);
var entity = dbSet.Add((T)res);
await entity.Context.SaveChangesAsync();
// var resource = await Warehouse.New<T>("", options.Store, null, null, null, properties);
var id = store.TypesByType[typeof(T)].PrimaryKey.GetValue(resource);
// resource.Instance.Managers.AddRange(options.Store.Instance.Managers.ToArray());
await Warehouse.Put(id.ToString(), res, store, null, null, 0, manager);
// return resource;
//}
return (T)res;
}
//public static T CreateResource<T>(this IServiceProvider serviceProvider, object properties = null) where T : class, IResource
// => CreateResourceAsync<T>(serviceProvider, properties).Wait();
//public static async AsyncReply<T> CreateResourceAsync<T>(this IServiceProvider serviceProvider, T properties = null) where T : class, IResource
//{
// var options = serviceProvider.GetService<IDbContextOptions>().FindExtension<EsiurExtensionOptions<T>>();
public static DbContextOptionsBuilder UseEsiur(this DbContextOptionsBuilder optionsBuilder,
EntityStore store,
Func<DbContext> getter = null
// var resource = await Warehouse.New<T>("", options.Store, null, null, null, properties);
//IServiceCollection services = null
//string name = null,
//IResource parent = null,
//IPermissionsManager manager = null,
//Func<DbContext> dbContextProvider = null
)
// resource.Instance.Managers.AddRange(options.Store.Instance.Managers.ToArray());
// return resource;
//}
//public static T CreateResource<T>(this IServiceProvider serviceProvider, object properties = null) where T : class, IResource
// => CreateResourceAsync<T>(serviceProvider, properties).Wait();
public static DbContextOptionsBuilder UseEsiur(this DbContextOptionsBuilder optionsBuilder,
EntityStore store,
Func<DbContext> getter = null
//IServiceCollection services = null
//string name = null,
//IResource parent = null,
//IPermissionsManager manager = null,
//Func<DbContext> dbContextProvider = null
)
{
var extension = optionsBuilder.Options.FindExtension<EsiurExtensionOptions>();
if (extension == null)
{
var extension = optionsBuilder.Options.FindExtension<EsiurExtensionOptions>();
if (extension == null)
{
if (store == null)
return optionsBuilder;
store.Options = optionsBuilder.Options;
extension = new EsiurExtensionOptions(store);
}
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
return optionsBuilder;
if (store == null)
return optionsBuilder;
store.Options = optionsBuilder.Options;
extension = new EsiurExtensionOptions(store);
}
//public static DbContextOptionsBuilder<TContext> UseEsiur<TContext>(
// this DbContextOptionsBuilder<TContext> optionsBuilder,
// //DbContext context,
// string name = null,
// IResource parent = null,
// IPermissionsManager manager = null,
// Func<DbContext> dbContextProvider = null)
// where TContext : DbContext
//{
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
// var extension = optionsBuilder.Options.FindExtension<EsiurExtensionOptions>();
// if (extension == null)
// {
// var store = Warehouse.New<EntityStore>(name, null, parent, manager, new { Options = optionsBuilder, DbContextProvider = dbContextProvider }).Wait();
// extension = new EsiurExtensionOptions(store);
// //store.Options = optionsBuilder;
// //store.Options = extension;
// //store.DbContext = context;
// }
// ((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
// return optionsBuilder;
//}
return optionsBuilder;
}
//public static DbContextOptionsBuilder<TContext> UseEsiur<TContext>(
// this DbContextOptionsBuilder<TContext> optionsBuilder,
// //DbContext context,
// string name = null,
// IResource parent = null,
// IPermissionsManager manager = null,
// Func<DbContext> dbContextProvider = null)
// where TContext : DbContext
//{
// var extension = optionsBuilder.Options.FindExtension<EsiurExtensionOptions>();
// if (extension == null)
// {
// var store = Warehouse.New<EntityStore>(name, null, parent, manager, new { Options = optionsBuilder, DbContextProvider = dbContextProvider }).Wait();
// extension = new EsiurExtensionOptions(store);
// //store.Options = optionsBuilder;
// //store.Options = extension;
// //store.DbContext = context;
// }
// ((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
// return optionsBuilder;
//}
}

View File

@@ -30,31 +30,29 @@ using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Stores.EntityCore
namespace Esiur.Stores.EntityCore;
public class EsiurPlugin : IConventionSetPlugin
{
public class EsiurPlugin : IConventionSetPlugin
private readonly IDbContextOptions _options;
private readonly ProviderConventionSetBuilderDependencies _conventionSetBuilderDependencies;
public EsiurPlugin(
IDbContextOptions options,
ProviderConventionSetBuilderDependencies conventionSetBuilderDependencies)
{
private readonly IDbContextOptions _options;
private readonly ProviderConventionSetBuilderDependencies _conventionSetBuilderDependencies;
public EsiurPlugin(
IDbContextOptions options,
ProviderConventionSetBuilderDependencies conventionSetBuilderDependencies)
{
_options = options;
_conventionSetBuilderDependencies = conventionSetBuilderDependencies;
}
public ConventionSet ModifyConventions(ConventionSet conventionSet)
{
var extension = _options.FindExtension<EsiurExtensionOptions>();
conventionSet.ModelFinalizingConventions.Add(new EsiurProxyRewrite(
extension,
_conventionSetBuilderDependencies));
return conventionSet;
}
_options = options;
_conventionSetBuilderDependencies = conventionSetBuilderDependencies;
}
public ConventionSet ModifyConventions(ConventionSet conventionSet)
{
var extension = _options.FindExtension<EsiurExtensionOptions>();
conventionSet.ModelFinalizingConventions.Add(new EsiurProxyRewrite(
extension,
_conventionSetBuilderDependencies));
return conventionSet;
}
}

View File

@@ -39,135 +39,157 @@ using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Esiur.Data;
namespace Esiur.Stores.EntityCore
namespace Esiur.Stores.EntityCore;
public class EsiurProxyRewrite : IModelFinalizingConvention
{
public class EsiurProxyRewrite : IModelFinalizingConvention
private static readonly MethodInfo _createInstance
= typeof(EsiurProxyRewrite).GetTypeInfo().GetDeclaredMethod(nameof(EsiurProxyRewrite.CreateInstance));
private readonly ConstructorBindingConvention _directBindingConvention;
public static object CreateInstance(IDbContextOptions dbContextOptions,
IEntityType entityType,
object[] properties)
{
private static readonly MethodInfo _createInstance
= typeof(EsiurProxyRewrite).GetTypeInfo().GetDeclaredMethod(nameof(EsiurProxyRewrite.CreateInstance));
var id = properties.First();
private readonly ConstructorBindingConvention _directBindingConvention;
var options = dbContextOptions.FindExtension<EsiurExtensionOptions>();
var manager = options.Store.Instance.Managers.Count > 0 ? options.Store.Instance.Managers.First() : null;
//public static object CreateInstance(IDbContextOptions dbContextOptions, IEntityType entityType,
// object[] constructorArguments, DbContext context, long id)
//{
// return CreateInstance(dbContextOptions, entityType,
// constructorArguments, context, id);
//}
var cache = options.Store.GetById(entityType.ClrType, id);
public static object CreateInstance(
IDbContextOptions dbContextOptions,
IEntityType entityType,
//object id
object[] properties
if (cache != null)
return cache;
// ILazyLoader loader,
// object[] constructorArguments,
//DbContext context,
)
if (Codec.ImplementsInterface(entityType.ClrType, typeof(IResource)))
{
var id = properties.First();
var options = dbContextOptions.FindExtension<EsiurExtensionOptions>();
var manager = options.Store.Instance.Managers.Count > 0 ? options.Store.Instance.Managers.First() : null;
var cache = options.Store.GetById(entityType.ClrType, id);
if (cache != null)
return cache;
if (Codec.ImplementsInterface(entityType.ClrType, typeof(IResource)))
{
// check if the object exists
var obj = Warehouse.New(entityType.ClrType).Wait() as IResource;
options.Store.TypesByType[entityType.ClrType].PrimaryKey.SetValue(obj, id);
Warehouse.Put(id.ToString(), obj, options.Store, null, null, 0, manager).Wait();
return obj;
}
else
{
// record
var obj = Activator.CreateInstance(entityType.ClrType);
options.Store.TypesByType[entityType.ClrType].PrimaryKey.SetValue(obj, id);
return obj;
}
}
public EsiurProxyRewrite(EsiurExtensionOptions ext, ProviderConventionSetBuilderDependencies conventionSetBuilderDependencies)
{
_directBindingConvention = new ConstructorBindingConvention(conventionSetBuilderDependencies);
// check if the object exists
var obj = Warehouse.New(entityType.ClrType).Wait() as IResource;
options.Store.TypesByType[entityType.ClrType].PrimaryKey.SetValue(obj, id);
Warehouse.Put(id.ToString(), obj, options.Store, null, null, 0, manager).Wait();
return obj;
}
public void ProcessModelFinalizing(IConventionModelBuilder modelBuilder, IConventionContext<IConventionModelBuilder> context)
else
{
foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
// record
var obj = Activator.CreateInstance(entityType.ClrType);
options.Store.TypesByType[entityType.ClrType].PrimaryKey.SetValue(obj, id);
return obj;
}
}
public EsiurProxyRewrite(EsiurExtensionOptions ext, ProviderConventionSetBuilderDependencies conventionSetBuilderDependencies)
{
_directBindingConvention = new ConstructorBindingConvention(conventionSetBuilderDependencies);
}
public void ProcessModelFinalizing(IConventionModelBuilder modelBuilder, IConventionContext<IConventionModelBuilder> context)
{
foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
{
if (!Codec.ImplementsInterface(entityType.ClrType, typeof(IResource)))
continue;
var proxyType = ResourceProxy.GetProxy(entityType.ClrType);
// var ann = entityType.GetAnnotation(CoreAnnotationNames.ConstructorBinding);
#pragma warning disable EF1001 // Internal EF Core API usage.
var binding = ((EntityType)entityType).ConstructorBinding;// (InstantiationBinding)entityType[CoreAnnotationNames.ConstructorBinding];
#pragma warning restore EF1001 // Internal EF Core API usage.
if (binding == null)
{
_directBindingConvention.ProcessModelFinalizing(modelBuilder, context);
#pragma warning disable EF1001 // Internal EF Core API usage.
binding = ((EntityType)entityType).ConstructorBinding; // (InstantiationBinding)entityType[CoreAnnotationNames.ConstructorBinding];
#pragma warning restore EF1001 // Internal EF Core API usage.
}
try
{
if (!Codec.ImplementsInterface(entityType.ClrType, typeof(IResource)))
var key = entityType.FindPrimaryKey().Properties.First();
if (key == null)
continue;
var proxyType = ResourceProxy.GetProxy(entityType.ClrType);
// var ann = entityType.GetAnnotation(CoreAnnotationNames.ConstructorBinding);
((EntityType)entityType).SetConstructorBinding(
UpdateConstructorBindings(key, proxyType),
ConfigurationSource.Convention);
#pragma warning disable EF1001 // Internal EF Core API usage.
var binding = (InstantiationBinding)entityType[CoreAnnotationNames.ConstructorBinding];
#pragma warning restore EF1001 // Internal EF Core API usage.
if (binding == null)
_directBindingConvention.ProcessModelFinalizing(modelBuilder, context);
#pragma warning disable EF1001 // Internal EF Core API usage.
binding = (InstantiationBinding)entityType[CoreAnnotationNames.ConstructorBinding];
#pragma warning restore EF1001 // Internal EF Core API usage.
try
binding = ((EntityType)entityType).ServiceOnlyConstructorBinding;
if (binding != null)
{
var key = entityType.FindPrimaryKey().Properties.First();
if (key == null)
continue;
//var keys = entityType.FindPrimaryKey().Properties.Select(x=>new PropertyParameterBinding(x));
entityType.SetAnnotation(
#pragma warning disable EF1001 // Internal EF Core API usage.
CoreAnnotationNames.ConstructorBinding,
#pragma warning restore EF1001 // Internal EF Core API usage.
new FactoryMethodBinding(
_createInstance,
new List<ParameterBinding>
{
new DependencyInjectionParameterBinding(typeof(IDbContextOptions), typeof(IDbContextOptions)),
new EntityTypeParameterBinding(),
//new PropertyParameterBinding(key)
// constructor arguments
//new ObjectArrayParameterBinding(binding.ParameterBindings),
//new ContextParameterBinding(typeof(DbContext)),
//new ObjectArrayParameterBinding(entityType.FindPrimaryKey().Properties.Select(x=>new PropertyParameterBinding(x)).ToArray())
new ObjectArrayParameterBinding(new ParameterBinding[]{
new PropertyParameterBinding(key) })
//})
// new Microsoft.EntityFrameworkCore.Metadata.ObjectArrayParameterBinding(),
//new ObjectArrayParameterBinding()
},
proxyType));
((EntityType)entityType).SetServiceOnlyConstructorBinding(
UpdateConstructorBindings(key, proxyType),
ConfigurationSource.Convention);
}
catch
{
}
// entityType.SetAnnotation(
//#pragma warning disable EF1001 // Internal EF Core API usage.
// CoreAnnotationNames.ConstructorBinding,
//#pragma warning restore EF1001 // Internal EF Core API usage.
// new FactoryMethodBinding(
// _createInstance,
// new List<ParameterBinding>
// {
// new DependencyInjectionParameterBinding(typeof(IDbContextOptions), typeof(IDbContextOptions)),
// new EntityTypeParameterBinding(),
// //new PropertyParameterBinding(key)
// // constructor arguments
// //new ObjectArrayParameterBinding(binding.ParameterBindings),
// //new ContextParameterBinding(typeof(DbContext)),
// //new ObjectArrayParameterBinding(entityType.FindPrimaryKey().Properties.Select(x=>new PropertyParameterBinding(x)).ToArray())
// new ObjectArrayParameterBinding(new ParameterBinding[]{
// new PropertyParameterBinding(key) })
// //})
// // new Microsoft.EntityFrameworkCore.Metadata.ObjectArrayParameterBinding(),
// //new ObjectArrayParameterBinding()
// },
// proxyType));
}
catch
{
}
}
}
private InstantiationBinding UpdateConstructorBindings(
IConventionProperty key,
Type proxyType)
{
return new FactoryMethodBinding(
_createInstance,
new List<ParameterBinding>
{
new DependencyInjectionParameterBinding(typeof(IDbContextOptions), typeof(IDbContextOptions)),
new EntityTypeParameterBinding(),
new ObjectArrayParameterBinding(new ParameterBinding[]{
new PropertyParameterBinding((IProperty)key) })
},
proxyType);
}
}