-
-
Notifications
You must be signed in to change notification settings - Fork 198
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow describing an index from a given Type
.
#525
Conversation
Support dynamic Index type
Hi @MikeAlhayek , All problems resolved |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hyzx86 I simplified things. I also removed the update you had to the readme file. That can be part of the Wiki once this PR is merged.
Type
.
@MikeAlhayek Thanks for your help . |
I guess since it's just to ensure the index is created using type, we could also have left it in the SQLite only. It does not matter either way. It does not hurt running it on all databases either |
@@ -67,20 +68,13 @@ protected static void GetProperties(DbCommand command, object item, string suffi | |||
|
|||
protected static PropertyInfo[] TypePropertiesCache(Type type) | |||
{ | |||
if (TypeProperties.TryGetValue(type, out var pis)) | |||
if (TypeProperties.TryGetValue(type.FullName, out var pis)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is mainly to avoid a scenario
Because dynamically typed indexes are allowed in the code, there is no guarantee that the type will not change during use,
For example, when I save the type, it has 5 fields, and then I add a new field, then I need to regenerate the type index.
Two types of inconsistent errors occur
2023-12-29 10:42:33.4084|SalesProtalDev|00-91aa5d5c1f96b614b2ebf3f2e6dfdbd5-5d2a9c17352de5d4-00||OrchardCore.ContentManagement.DefaultContentManager|ERROR|IContentHandler thrown from OrchardCore.Contents.AuditTrail.Handlers.AuditTrailContentHandler by InvalidCastException System.InvalidCastException: [A]EasyOC.DynamicIndex.AmisSchemaDIndex cannot be cast to [B]EasyOC.DynamicIndex.AmisSchemaDIndex. Type A originates from 'DynamicTypesAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'Default' in a byte array. Type B originates from 'DynamicTypesAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'Default' in a byte array.
at YesSql.Serialization.PropertyInfoAccessor.Invoker`2.Invoke(Object target)
at YesSql.Commands.IndexCommand.GetProperties(DbCommand command, Object item, String suffix, ISqlDialect dialect)
at YesSql.Commands.CreateIndexCommand.AddToBatch(ISqlDialect dialect, List`1 queries, DbCommand batchCommand, List`1 actions, Int32 index)
at YesSql.Session.BatchCommands()
at YesSql.Session.FlushAsync()
at YesSql.Session.FlushAsync()
at YesSql.Services.DefaultQuery.CountAsync()
at YesSql.Services.DefaultQuery.QueryIndex`1.YesSql.IQueryIndex<T>.CountAsync()
at OrchardCore.Contents.AuditTrail.Handlers.AuditTrailContentHandler.RecordAuditTrailEventAsync(String name, IContent content)
at OrchardCore.Modules.InvokeExtensions.InvokeAsync[TEvents,T1](IEnumerable`1 events, Func`3 dispatch, T1 arg1, ILogger logger) at YesSql.Serialization.PropertyInfoAccessor.Invoker`2.Invoke(Object target)
at YesSql.Commands.IndexCommand.GetProperties(DbCommand command, Object item, String suffix, ISqlDialect dialect)
at YesSql.Commands.CreateIndexCommand.AddToBatch(ISqlDialect dialect, List`1 queries, DbCommand batchCommand, List`1 actions, Int32 index)
at YesSql.Session.BatchCommands()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because the index type may change while the program is running.
Just like this:
thrown from OrchardCore.Contents.AuditTrail.Handlers.AuditTrailContentHandler by InvalidCastException System.InvalidCastException: [A]EasyOC.DynamicIndex.AmisSchemaDIndex cannot be cast to [B]EasyOC.DynamicIndex.AmisSchemaDIndex. Type A originates from 'DynamicTypesAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'Default' in a byte array. Type B originates from 'DynamicTypesAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'Default' in a byte array.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There seems to be no way to reproduce this scenario in a unit test, or to reproduce this scenario would require a complicated process
@MikeAlhayek I reupdated the code protected static PropertyInfo[] TypePropertiesCache(Type type)
{
if (TypeProperties.TryGetValue(type, out var pis))
{
return pis;
}
+ // If the same name type is already cached, it should be removed from the cache.
+ var existsingType = TypeProperties.Keys.FirstOrDefault(x => x.FullName == type.FullName);
+ if (existsingType != null)
+ {
+ var existsingProps = TypeProperties[existsingType];
+ foreach (var prop in existsingProps)
+ {
+ PropertyAccessors.Remove(prop, out _);
+ }
+
+ TypeProperties.Remove(existsingType, out _);
+ }
var properties = type.GetProperties().Where(IsWriteable).ToArray();
TypeProperties[type] = properties;
return properties;
} |
Co-authored-by: Hisham Bin Ateya <[email protected]>
Co-authored-by: Hisham Bin Ateya <[email protected]>
Co-authored-by: Hisham Bin Ateya <[email protected]>
Co-authored-by: Hisham Bin Ateya <[email protected]>
Co-authored-by: Hisham Bin Ateya <[email protected]>
OC registers a singleton so it wouldn't be creating multiple |
The code have changes since it was approved
Not really, pls see session.RegisterIndexes |
@hyzx86 have you tried implementing |
Yes, but eventually I gave up
It's only used when you delete an index, because the map index returns null when you delete an index, so you can't get its type in Clearly limit the use of
|
If you use |
If you need to create
You may want to add interface to the abstraction project maybe like this
The But, I am not sure that the complexity added by |
@MikeAlhayek updated the default index cache key Now , you can modify the test Comment on the following line // update index type cache
store1.Configuration.IndexTypeCacheProvider?.UpdateCachedType(changedType); And run the test ,Errors will be reproduced There is nothing wrong with using the full name of the type as the Key for the cache. As I mentioned before, dynamically indexed types may change the list of fields during the program run, so each time an indexed field is modified, a new type is generated. However, in an OC or other project , it may be better to replace it with an in-memory cache or a distributed cache, since both of these are tenant isolated in an OC. And we can define the full name of the class to start with the tenant name when using dynamic type generation |
# Conflicts: # src/Directory.Packages.props
…nto dynamicIndexType
{ | ||
return pis; | ||
} | ||
|
||
// Clean up cache entries with the same name and different type | ||
var exists = TypeProperties.Keys.FirstOrDefault(x => x.FullName == type.FullName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To ensure that only meaningful types are cached, cached type with the same name will cleared
@@ -67,20 +68,13 @@ protected static void GetProperties(DbCommand command, object item, string suffi | |||
|
|||
protected static PropertyInfo[] TypePropertiesCache(Type type) | |||
{ | |||
if (TypeProperties.TryGetValue(type, out var pis)) | |||
if (TypeProperties.TryGetValue(type.FullName, out var pis)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There seems to be no way to reproduce this scenario in a unit test, or to reproduce this scenario would require a complicated process
getterIL.Emit(OpCodes.Ldfld, fieldBuilder); | ||
getterIL.Emit(OpCodes.Ret); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.None, propType, null); | ||
FieldBuilder fieldBuilder = typeBuilder.DefineField("_" + propertyName, propType, FieldAttributes.Private); | ||
|
||
// 使用 IL API 生成类型属性访问器 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
// Return the dynamic type | ||
return dynamicType; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
using System.Reflection.Emit; | ||
using YesSql.Indexes; | ||
|
||
namespace YesSql.Tests.Indexes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
Assert.NotEmpty(testProperties2); | ||
|
||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
} | ||
|
||
protected bool IsWriteable(PropertyInfo pi) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MikeAlhayek Because this method is needed for caching in Yessql, I changed the original IIndexTypeCacheProvider to IndexTypeCacheProvider and included some virtual methods
/// This interface needs to be reimplemented when dynamic type and multi-tenant scenarios are used, | ||
/// using tenant separated cache media insteadexTypeCacheProvider | ||
/// </summary> | ||
IndexTypeCacheProvider IndexTypeCacheProvider { get; set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MikeAlhayek We need to add it to the IConfiguration
so that it can be overridden by other implementations
So I extracted IndexTypeCacheProvider
into the Abstraction project
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for taking so long to reply. Because I didn't submit my comments 😢
I always wondered why there was a Pendding
mark on my reply. I just figured it out.
# Conflicts: # src/Directory.Packages.props
After a period of test run, it is found that this method is not reliable Next I'm going to try to implement |
Here is an example