有没有办法在运行时使用codeDOM生成的实体上调用通用存储库方法?

时间:2015-06-18 23:05:05

标签: c# entity-framework generics reflection codedom

我正在使用codeDOM在运行时生成我的实体类。我还有一个通用的存储库来处理各种数据库功能。这是作为我的通用存储库中的示例方法的Insert方法:

public void Insert<TEntity>(TEntity entity) where TEntity : class, IBusinessEntity
{
    if (entity == null)
    {
        throw new ArgumentNullException("entity");
    }

    TEntity existing = Existing(entity);
    if (existing == null)
    {
        _context.Set<TEntity>().Add(entity);
        this._context.SaveChanges();
    }
}

以下是我如何生成实体类以及如何使用codeDOM基于该实体类创建实体的示例代码:

//Generate the fields of the new entity class
EntityGenerator.EntityFieldInfo entityField1 = new EntityGenerator.EntityFieldInfo("Name", typeof(string), RelationshipType.NoRelation);
EntityGenerator.EntityFieldInfo entityField2 = new EntityGenerator.EntityFieldInfo("Shape", typeof(string), RelationshipType.NoRelation);
ICollection<EntityGenerator.EntityFieldInfo> entityFieldList = new List<EntityGenerator.EntityFieldInfo> { entityField1, entityField2 };

// Create the new entity class using the fields established above 
// as well as the name of the entity (typeName = "Thing")
string typeName = "Thing";
EntityGenerator.CreateEntityClass(entityFieldList, typeName);
CompilerResults results = EntityGenerator.GetCompiledEntity(typeName);

// Create an entity instance based on the new entity class that was just created
Object newThing = EntityGenerator.CreateInstanceOfEntity(results, typeName);
SetObjectField(newEntity, "Name", "Box");
SetObjectField(newEntity, "Shape", "Cuboid");

如您所见,newThing(新实体实例)是一种Object类型。如果这是一个硬编码的实体类,那么我可以说

Thing newThing;

但CodeDOM创建的Thing实体不是硬编码类,因此我必须使用Object类型而不是Thing类型。这是一个问题,因为我使用的是通用存储库。让我们说我想将这个实体插入数据库。我想打个电话:

myRepository.Insert<Thing>(newThing);

但是,Thing只是在运行时由CodeDOM创建的,所以它不是一个类,这意味着它不能进入​​&lt;&gt;。您可能已经在我的Insert方法中注意到,TEntity也是一个IBusinessEntity。如果我试试

myRepository.Insert<IBusinessEntity>(newThing);

我收到错误:

  

参数类型&#39;对象&#39;不能分配给参数类型&#39; Models.IBusinessEntity&#39;

如果我在&lt;&gt;中没有任何内容尝试,请执行以下操作:

myRepository.Insert(newThing);

我收到错误:

  

类型&#39;对象&#39;必须可转换为&#39; Models.IBusinessEntity&#39;为了将它用作参数&#39; TEntity&#39;在通用方法&#39; void Insert(TEntity)&#39;。

有谁知道如何协调这个codeDOM生成的实体与通用存储库?反思有帮助吗?如果反思可以某种方式给我一类可以传递给&lt;&gt;的东西,那将是很好的。另外我应该注意,我使用CodeDOM创建的所有实体都扩展了IBusinessEntity。

1 个答案:

答案 0 :(得分:1)

我认为很难使它工作,因为DbContext中包含的DbSets被EF用来创建映射。你觉得如何创造它们?

无论如何,您不需要使用EF类型,您通常可以使用GetType。 在您的方法中(缺少现有(。)但我认为类似)您可以使用

public void Insert(object entity)
{
    if (entity == null)
        throw new ArgumentNullException("entity");

    if (!(entity is IBusinessEntity))
        throw new ArgumentInvalidException("entity is not an IBusinessEntity");

    object existing = Existing(entity);
    if (existing == null)
    {
        _context.Set(entity.GetType()).Add(entity);
        this._context.SaveChanges();
    }

}

使用Set&lt;&gt;或Set(。)我很确定EF将搜索从DbContext中包含的DbSets开始创建的映射。我不记得确切的异常,但我播种的时间不同(当我使用DbContext.Set(myEntityType)时)。