我正在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);
}

推荐答案

创建EntityTypeBuilder<>的实例对我来说有点奇怪(请注意,它有single ctor个接受IMutableEntityType的实例,而不是Type):

var entityTypeBuilderType = typeof(EntityTypeBuilder<>).MakeGenericType(entityType);
// ....
Activator.CreateInstance(entityTypeBuilderType, entityType);

由于您已超过ModelBuilder,您可以try 使用Entity方法modelBuilder.Entity(entityType)的非泛型版本(对代码进行相应的更改),或者try 找到泛型方法并调用它(例如,模拟modelBuilder.Entity<...>调用):

var methodInfo = typeof(ModelBuilder).GetMethod(
    nameof(ModelBuilder.Entity), 
    genericParameterCount: 1, 
    types: Type.EmptyTypes);
var genericMethod = methodInfo.MakeGenericMethod(typeof(entityType));
var entityBuilder = genericMethod.Invoke(modelBuilder, null); // instead of Activator.CreateInstance

Csharp相关问答推荐

当前代码Cosmos DB 3.37.1:PartitionKey key key mismatch exception

有没有更好的方法来在CosmosDB上插入非id?

使用System.Text.Json进行序列化时发生StackOverflow异常

未显示详细信息的弹出对话框

RCL在毛伊岛应用程序和Blazor服务器应用程序.Net 8.0中使用页面

EF Core 7-忽略模型绑定中的虚拟属性

C#USB条形码 scanner 在第二次扫描时未写入行尾字符

如何将 colored颜色 转换为KnownColor名称?

映射器-如何映射到多个实体

Xamarin Forms应用程序中登录页面的用户名和密码编辑文本之间不需要的空格

C#;AvaloniaUI;MVVM;当另一个窗口上的按钮被单击时,如何更新视图图像源?

如何模拟一个返回OneOf IServiceA,IServiceB的方法?使用Moq

如何在Blazor 8 RC2静态模式下以编程方式导航到另一个页面

从API调用调用Worker服务方法

未调用Blazor MudForm验证函数,因为最初未显示MudTextField

从系统中获取值__C中的对象#

是否通过导航属性删除实体?

如何在C#中使用Newtonsoft将两个属性序列化为一个json属性?

当异步函数被挂起时,所有的值类型都会受到GC的约束吗?

如何使用MediaInfo库在C#/.NET中提取封面艺术?