2016-02-05 3 views
0

Мне нужно получить все TEntitys из 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); 
}     

Этот метод возвращает все данные из указанного DbSet по имени и теллур указано DbContext

public List<TEntity> GetLocal<TEntity>(string name, DbContext ctx) 
{ 
    var enumerable = (IEnumerable<TEntity>)(typeof([ClassNameOfMyContext]).GetProperty(name).GetValue(ctx, null)); 
    return enumerable.ToList(); 
} 

Этот метод получить свойства от моего DbContext. Я использую это для получить весь DbSets в моем DbContext

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; 
} 
+0

Цель этого кода - получить все данные от каждого объекта в вашем dbcontext? –

+0

Да, я делаю синхронизатор базы данных – Richard

+0

Не намного ли проще использовать 'context.Set () .ToList();' поэтому как 'context.Set () .ToList()' –

ответ

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

Примечание: Я не проверял это, но я использовал принцип много раз.

+0

«Тип не содержит определения для« Сделать общий »и не использует метод расширения, который принимает первый аргумент типа« Тип », найденный« – Richard

+0

Должен быть Type.MakeGenericType. Я исправлю это позже. – Maarten

+0

Я попытался использовать ваше решение и выдал мне следующую ошибку: Вы не можете преобразовать объект типа 'System.Data.Entity.DbSet'1 [myEntity]', чтобы ввести 'System.Collections.Generic.IEnumerable'1 [System .Data.Entity.DbSet'1 [myEntity]] '. – Richard

Смежные вопросы