如何通过名称获得TEntity

时间:2016-02-05 17:57:29

标签: c# entity-framework

我需要从mi DbContext获取所有TEntity来从每个表中提取所有信息。我有一些信息很少的桌子。 我有这个代码但是没有用。

var dbSetPropertiesLocal = local.GetDbSetProperties();                

foreach (var item in dbSetPropertiesLocal)
{
    Type type = item.PropertyType; // This need get the type of the actual TEntity
    var enumerable = GetLocal<type>(item.Name, local);  
}                 

此方法按名称和指定的DbContext

返回指定DbSet中的所有数据
public List<TEntity> GetLocal<TEntity>(string name, DbContext ctx)
{
    var enumerable = (IEnumerable<TEntity>)(typeof([ClassNameOfMyContext]).GetProperty(name).GetValue(ctx, null));
    return enumerable.ToList();
}

此方法从我的DbContext获取属性。我使用它来获取我的DbContext中的所有DbSet

public static List<PropertyInfo> GetDbSetProperties(this DbContext context)
{
    var dbSetProperties = new List<PropertyInfo>();
    var properties = context.GetType().GetProperties();

    foreach (var property in properties)
    {
        var setType = property.PropertyType;
        var isDbSet = setType.IsGenericType && (typeof(IDbSet<>).IsAssignableFrom(setType.GetGenericTypeDefinition()) || setType.GetInterface(typeof(IDbSet<>).FullName) != null);

        if (isDbSet)
            dbSetProperties.Add(property);
    }

    return dbSetProperties;
}

1 个答案:

答案 0 :(得分:2)

我不确定您当前的路径是否是解决更大问题的最佳方法(实现数据库同步器)。但这是解决您较小问题的方法(调用您的通用代码)。

创建泛型类,使用反射创建实例,而不是扩展方法。此外,添加一个接口以与实例通信。请记住,该类可能是通用的,但如果您必须从非泛型代码与它进行对话,那么您需要一个接口来从泛型类实例转换为非泛型接口实例(如果您知道我的意思)。

public interface ILocalEntityListProvider {
    List<object> GetLocal(string name, DbContext ctx);
}
public class LocalEntityListProvider<TEntity> : ILocalEntityListProvider {
    private IEnumerable<TEntity> GetLocal(string name, DbContext ctx)
    {
        return (IEnumerable<TEntity>)(typeof([ClassNameOfMyContext])
            .GetProperty(name)
            .GetValue(ctx, null));
    }

    List<object> ILocalEntityListProvider.GetLocal(string name, DbContext ctx) {
        return GetLocal(name, ctx)
            .Cast<object>()
            .ToList();
    }
}

var dbSetPropertiesLocal = local.GetDbSetProperties();                
foreach (var item in dbSetPropertiesLocal)
{
    var entityType = item.PropertyType.GenericTypeArguments.First();
    var providerClassType = typeof(LocalEntityListProvider<>).MakeGeneric(entityType);
    var providerInstance = Activator.CreateInstance(providerClassType) as ILocalEntityListProvider;
    var enumerable = providerInstance.GetLocal(item.Name, local);  
}

注意:我没有对此进行过测试,但我已多次使用该原理。