我正在try 从非泛型版本使用System.Reflect调用泛型版本.
当我运行迁移时,我收到以下错误:
‘Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder`1[[Domain.BalanceSnapshot,域类型上的构造函数,版本=1.0.0.0,区域性=中性,PublicKeyTo Ken=空]]‘未找到.
为什么?我该怎么修好它?
public static void HasTenancy<TTenantKey>(
this ModelBuilder modelBuilder,
Type entityType,
Expression<Func<TTenantKey>> tenantId,
TenancyModelState<TTenantKey> tenancyModelState,
string propertyName = null,
bool? hasIndex = null,
string indexNameFormat = null,
NullTenantReferenceHandling? nullTenantReferenceHandling = null)
{
var entityTypeBuilderType = typeof(EntityTypeBuilder<>).MakeGenericType(entityType);
var expressionTenantIdType = typeof(Expression<>).MakeGenericType(typeof(Func<>).MakeGenericType(typeof(TTenantKey)));
var tenancyModelStateType = typeof(TenancyModelState<>).MakeGenericType(typeof(TTenantKey));
var parameterTypes = new[]
{
entityTypeBuilderType,
expressionTenantIdType,
tenancyModelStateType,
typeof(string),
typeof(bool?),
typeof(string),
typeof(NullTenantReferenceHandling?)
};
var method = typeof(TenancyEFExtensions)
.GetMethods(BindingFlags.Public | BindingFlags.Static)
.Where(m => m.Name == nameof(HasTenancy))
.FirstOrDefault(m => m.GetParameters()
.Select(p => p.ParameterType.IsGenericType ? p.ParameterType.GetGenericTypeDefinition() : p.ParameterType)
.SequenceEqual(parameterTypes.Select(t => t.IsGenericType ? t.GetGenericTypeDefinition() : t)))?.MakeGenericMethod(entityType, typeof(TTenantKey));
method?.Invoke(null, new[]
{
Activator.CreateInstance(entityTypeBuilderType, entityType),
tenantId,
tenancyModelState,
propertyName,
hasIndex,
indexNameFormat,
nullTenantReferenceHandling
});
}
public static void HasTenancy<TEntity, TTenantKey>(this EntityTypeBuilder<TEntity> builder,
Expression<Func<TTenantKey>> tenantId,
TenancyModelState<TTenantKey> tenancyModelState,
string propertyName = null,
bool? hasIndex = null,
string indexNameFormat = null,
NullTenantReferenceHandling? nullTenantReferenceHandling = null)
where TEntity : class
{
ArgCheck.NotNull(nameof(builder), builder);
ArgCheck.NotNull(nameof(tenancyModelState), tenancyModelState);
// get overrides or defaults
var tenantKeyType = typeof(TTenantKey);
propertyName ??= tenancyModelState.DefaultOptions.ReferenceName ?? throw new ArgumentNullException(nameof(propertyName));
hasIndex ??= tenancyModelState.DefaultOptions.IndexReferences;
indexNameFormat ??= tenancyModelState.DefaultOptions.IndexNameFormat;
nullTenantReferenceHandling ??= tenancyModelState.DefaultOptions.NullTenantReferenceHandling;
tenancyModelState.Properties[typeof(TEntity)] = new()
{
ReferenceName = propertyName,
IndexReferences = hasIndex.Value,
IndexNameFormat = indexNameFormat,
NullTenantReferenceHandling = nullTenantReferenceHandling.Value
};
// add property
var property = builder.Property(tenantKeyType, propertyName);
// is required / not null
if (nullTenantReferenceHandling == NullTenantReferenceHandling.NotNullDenyAccess ||
nullTenantReferenceHandling == NullTenantReferenceHandling.NotNullGlobalAccess)
{
property.IsRequired();
}
// add index
if (hasIndex.Value)
{
var index = builder.HasIndex(propertyName);
if (!string.IsNullOrEmpty(indexNameFormat))
{
index.HasName(string.Format(indexNameFormat, propertyName));
}
}
// add tenant query filter
// Entity e
var entityParameter = Expression.Parameter(typeof(TEntity), "e");
// "TenantId"
var propertyNameConstant = Expression.Constant(propertyName, typeof(string));
// EF.Property<long>
var efPropertyMethod = ((MethodCallExpression)((Expression<Func<object, string, TTenantKey>>)((e, p) => EF.Property<TTenantKey>(e, p))).Body).Method;
// EF.Property<long>(e, "TenantId")
var efPropertyCall = Expression.Call(efPropertyMethod, entityParameter, propertyNameConstant);
// _tenancyContext.Tenant.Id == EF.Property<long>(e, "TenantId")
var tenantCondition = Expression.Equal(tenantId.Body, efPropertyCall);
if (nullTenantReferenceHandling == NullTenantReferenceHandling.NotNullDenyAccess ||
nullTenantReferenceHandling == NullTenantReferenceHandling.NotNullGlobalAccess)
{
var nullableTenantKeyType = tenantKeyType.IsValueType ? typeof(Nullable<>).MakeGenericType(tenantKeyType) : tenantKeyType;
var nullableTenantKey = tenantKeyType.IsValueType ? Expression.Convert(tenantId.Body, nullableTenantKeyType) : tenantId.Body;
var nullTenantKey = Expression.Constant(null, nullableTenantKeyType);
if (nullTenantReferenceHandling == NullTenantReferenceHandling.NotNullDenyAccess)
{
// (long?)_tenancyContext.Tenant.Id != (long?)null && _tenancyContext.Tenant.Id == EF.Property<long>(e, "TenantId")
tenantCondition = Expression.AndAlso(Expression.NotEqual(nullableTenantKey, nullTenantKey), tenantCondition);
}
else if (nullTenantReferenceHandling == NullTenantReferenceHandling.NotNullGlobalAccess)
{
// (long?)_tenancyContext.Tenant.Id == (long?)null || _tenancyContext.Tenant.Id == EF.Property<long>(e, "TenantId")
tenantCondition = Expression.OrElse(Expression.Equal(nullableTenantKey, nullTenantKey), tenantCondition);
}
}
var lambda = Expression.Lambda(tenantCondition, entityParameter);
builder.HasQueryFilter(lambda);
}