【问题标题】:How to get TEntity by name如何按名称获取 TEntity
【发布时间】:2016-02-10 05:21:03
【问题描述】:

我需要从 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;
}

【问题讨论】:

  • 这段代码的目的是从你的 dbcontext 中的每个实体中获取所有数据?
  • 是的,我正在做一个数据库同步器
  • context.Set&lt;Users&gt;().ToList()这样使用context.Set&lt;T&gt;().ToList();是不是容易多了
  • 但是我不知道我的 DbContext 中有多少个 Entities,所以我需要做泛型。
  • 可以使用第三方库还是受限?添加 TPC、TPH 和 TPT 继承时,查找所有表/属性可能会有点困难。

标签: c# entity-framework


【解决方案1】:

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

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

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);  
}

注意:这个我没有测试过,但是这个原理我用过很多次了。

【讨论】:

  • “类型不包含“Make Generic”的定义,也没有找到接受“Type”类型的第一个参数的扩展方法”
  • 应该是Type.MakeGenericType。我稍后会修复它。
  • 我尝试使用您的解决方案并抛出以下错误:您无法转换类型为 'System.Data.Entity.DbSet1 [myEntity]' to type 'System.Collections.Generic.IEnumerable1 [System.Data.Entity.DbSet`1 的对象[myEntity]]'。
  • 是的,我现在可以看到了。固定我想,不确定,目前在我的手机上,你能检查一下吗?
  • 希望您能给我解决方案,非常感谢并标记您的答案。
猜你喜欢
  • 1970-01-01
  • 2014-10-20
  • 2014-08-17
  • 2016-08-05
  • 2012-05-16
  • 1970-01-01
  • 1970-01-01
  • 2012-05-30
相关资源
最近更新 更多