Найти актуальный DbSet для действий CRUD динамически - PullRequest
0 голосов
/ 12 декабря 2018

Я искал на этом сайте, и у меня возникают проблемы с получением фактического DbSet из моего контекстаЯ пытаюсь получить каждый dbset динамически на основе имени таблицы.

 var dynamicdbset = GetDbSetByTableName(uploadTableName); //Dbset name is Mytables


  private dynamic GetDbSetByTableName(string tableName)
        {
            MyEntities context = new MyEntities();
            System.Reflection.PropertyInfo[] properties = typeof(ClearGUIEntities).GetProperties();
            var prop = properties.FirstOrDefault(p => p.Name == tableName + "s");

            using (var db = new MyEntities())
            {
                var dbset = prop?.GetValue(db);
                return dbset;
            }

        }

Проблема здесь в том, что он возвращает некоторый общий набор данных dbset, но я не могу использовать linq и не могу выполнить простую операцию, такую ​​как

dynamicdbset.Where(t = > t.Id == 123).Single();

Мне нужно иметь возможность динамически получать набор данных по имени таблицы, а также запрашивать данные так же, как если бы я создал его, например,

var value = context.MyTables.FirstorDefault()

1 Ответ

0 голосов
/ 12 декабря 2018

Возвращенная динамика DbSet на самом деле является просто оберткой вокруг реального DbSet объекта, который вы можете просто привести к.Проблема, однако, в том, что тип DbSet не может быть выведен без использования универсального метода .

. Следующее сработало бы, но, вероятно, наименее предпочтительно:

private IEnumerable<T> GetDbSetByTableName<T>(string tableName)
{
    System.Reflection.PropertyInfo[] properties = typeof(ClearGUIEntities).GetProperties();
    var prop = properties.FirstOrDefault(p => p.Name == tableName + "s");

    using (var db = new ClearGUIEntities())
    {
        var dbset = prop?.GetValue(db);

        return new List<T>(dbset as IEnumerable<T>);
    }
}

Теперь, чтобы обойти это, у нас есть по крайней мере два варианта:

  1. Создать интерфейс (со всеми необходимыми базовыми свойствами), который реализуется всеми DbSet s.,Таким образом, мы можем привести динамический объект без необходимости указывать тип при конвертации.
  2. Возвращать IEnumerable<dynamic>, который можно кастовать на лету.

Опция 1

public interface IBaseProperties
{
    int Id { get; set; }
    string Name { get; set; }
}

public class MyTable : IBaseProperties
{
    // Add these with either T4 templates or create partial class for each of these entities
    public int Id { get; set; }
    public string Name { get; set; }
}

private IEnumerable<IBaseProperties> GetDbSetByTableName(string tableName)
{
    System.Reflection.PropertyInfo[] properties = typeof(ClearGUIEntities).GetProperties();
    var prop = properties.FirstOrDefault(p => p.Name == tableName + "s");

    using (var db = new ClearGUIEntities())
    {
        var dbset = prop?.GetValue(db);

        return new List<IBaseProperties>(dbset as IEnumerable<IBaseProperties>);
    }
}

// ...
// Using it
// ...

var dynamicdbset = GetDbSetByTableName("MyTable");

int id = dynamicdbset.FirstOrDefault().Id;

Опция 2

private IEnumerable<dynamic> GetDbSetByTableName(string tableName)
{
    System.Reflection.PropertyInfo[] properties = typeof(ClearGUIEntities).GetProperties();
    var prop = properties.FirstOrDefault(p => p.Name == tableName + "s");

    using (var db = new ClearGUIEntities())
    {
        var dbset = prop?.GetValue(db);

        return new List<dynamic>(dbset as IEnumerable<dynamic>);
    }
}

// ...

// At this point, you can basically access any property of this entity
// at the cost of type-safety
string id = dynamicdbset.FirstOrDefault().Id;
string name = dynamicdbset.FirstOrDefault().Name;

Кстати, приведение к List<T> необходимо, потому что вы используете объект вне блока using, в этот момент он был быраспоряжаться.

new List<IBaseProperties>(dbset as IEnumerable<IBaseProperties>);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...