[英]Generic Entity mapping in EF
I want to make a generic entity mapper that maps all entities to dbContext and EF.我想制作一个通用实体映射器,将所有实体映射到 dbContext 和 EF。 Currently, after I do Add-Migration init
, I receive an error:目前,在我执行Add-Migration init
之后,我收到一个错误:
Cannot create an instance of Models.DataMapping.EntityMapper`1[TEntity] because Type.ContainsGenericParameters is true.
I do not understand what this error exacly means and why if type ContainsGenericParameters
is true it should cause a crash.我不明白这个错误究竟意味着什么,以及为什么如果ContainsGenericParameters
类型为 true 会导致崩溃。 Any ideas what is wrong and how could I fix it?有什么想法有什么问题,我该如何解决?
This is my code:这是我的代码:
namespace Models.DataMapping
{
public interface IEntityMapper
{
void Map(ModelBuilder modelBuilder);
}
}
namespace Models.DataMapping
{
public abstract class EntityMapper<TEntity> :
IEntityMapper where TEntity : class
{
public void Map(ModelBuilder modelBuilder)
{
EntityTypeBuilder<TEntity> entityTypeBuilder = modelBuilder.Entity<TEntity>();
MapEntity(entityTypeBuilder);
}
protected virtual void MapEntity(EntityTypeBuilder<TEntity> entityTypeBuilder)
{
}
}
}
namespace Models.DataMapping
{
public static class EntityMappersProvider
{
public static IReadOnlyCollection<IEntityMapper> GetLocalEntityMappers() {
return Assembly.GetExecutingAssembly()
.GetTypes()
.Where(t => typeof(IEntityMapper).IsAssignableFrom(t) && t.IsClass)
.Select(t => (IEntityMapper)Activator.CreateInstance(t))
.ToArray();
}
}
}
Including provider in dbContext.在 dbContext 中包含提供程序。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
IReadOnlyCollection<IEntityMapper> entityMappers = EntityMappersProvider.GetLocalEntityMappers();
foreach (IEntityMapper mapper in entityMappers) {
mapper.Map(modelBuilder);
}
}
Example of Entity relationships realization.实体关系实现示例。
namespace Models.DataMapping.EntitiesMapping
{
public class CourseMapper : EntityMapper<Course>
{
protected override void MapEntity(EntityTypeBuilder<Course> entityTypeBuilder)
{
entityTypeBuilder.ToTable("Courses");
entityTypeBuilder.HasKey(a => a.Id);
//....
}
}
}
Also what I have noticed that if I remove abstract
keyword in EntityMapper
and add t.IsAbstract
in EntityMappersProvided
empty migration gets created..另外我注意到,如果我在EntityMappersProvided
中删除abstract
关键字并在EntityMapper
中添加t.IsAbstract
,则会创建空迁移..
For me it looks like you are trying to reinvent IEntityTypeConfiguration
which allows to move entity configuration code to separate classes:对我来说,您似乎正在尝试重新发明IEntityTypeConfiguration
,它允许将实体配置代码移动到单独的类:
public class BlogEntityTypeConfiguration : IEntityTypeConfiguration<Blog>
{
public void Configure(EntityTypeBuilder<Blog> builder)
{
builder
.Property(b => b.Url)
.IsRequired();
}
}
And provides convenience method to find all such configuration in assembly, which is available since EF Core 2.2 :并提供了在程序集中查找所有此类配置的便捷方法,该方法从EF Core 2.2开始可用:
modelBuilder.ApplyConfigurationsFromAssembly(typeof(BlogEntityTypeConfiguration).Assembly);
As for your error - it happens because your code tries to instantiate an open generic type ( EntityMapper<TEntity>
) with Activator.CreateInstance
:至于您的错误-发生这种情况是因为您的代码尝试使用Activator.CreateInstance
实例化一个开放的泛型类型( EntityMapper<TEntity>
):
public class OpenGeneric<T>{}
Activator.CreateInstance(typeof(OpenGeneric<>)); // throws Cannot create an instance of Generic`1[T] because Type.ContainsGenericParameters is true.
So you need to filter it out, for example by adding &&.t.IsAbstract && ! t.ContainsGenericParameters
因此,您需要将其过滤掉,例如通过添加&&.t.IsAbstract && ! t.ContainsGenericParameters
&&.t.IsAbstract && ! t.ContainsGenericParameters
in your Where
clause. &&.t.IsAbstract && ! t.ContainsGenericParameters
在Where
子句中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.