Создайте запрос select LINQ, упорядочивающий по первичному ключу без указания типа модели - PullRequest
0 голосов
/ 10 февраля 2020

У меня есть процесс, который в основном перемещает данные из одной базы данных в другую, и для этого существует целый ряд обработчиков сообщений. Чтобы мой процесс перемещения данных был динамичным c Я хотел разработать обобщенный процесс c с использованием настраиваемого атрибута в моих обработчиках сообщений, что позволило бы мне автоматически управлять миграцией данных.

Каждый обработчик сообщений имеет пользовательский атрибут, например

[BulkImport(EntityModelType = typeof(TblProxyCompany))]

Реализация атрибута следующая: -

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class BulkImportAttribute : Attribute
{
    public Type EntityModelType { get; set; }
    public Type[] DependentEntityModelTypes { get; set; }
}

Мой процесс миграции данных считывает все обработчики сообщений с этим атрибут, который создает мой список задач. В своем коде я выполняю oop через каждую задачу и отправляю сообщение в очередь локального хранилища, и именно здесь начинаются мои проблемы.

Мне нужно прочитать группу строк из таблицы, определенной в моем атрибуте через тип модели, т.е. TblProxyCompany, и запрос linq ниже делает это: -

var query = _oltpContext.Query(importItem.EntityModelType)
  .Cast<IBulkImport>()
  .Skip(skip)
  .Take(BATCH_SIZE);

Первая проблема, с которой я столкнулся, заключалась в том, что мой метод расширения Query возвращает IQueryable без типа модели, и из-за этого Я не мог использовать Skip and Take, поэтому приводил к интерфейсу IBulkImport.

Итак, я создал интерфейс IBulkImport и добавил его к каждому типу моей модели и просто преобразовал IQueryable в IQueryable<IBulkImport>, и теперь я могу использовать Skip and Take.

I затем обнаружил, что SQL возвращал мои данные в согласованном порядке, и, следовательно, мои пакеты были неправильными, поэтому теперь мне нужно упорядочить запрос по первичному ключу типа модели. К сожалению, хотя 99% моих таблиц имеют первичный ключ Id, не все из них имеют, поэтому я не мог просто добавить столбец Id в интерфейс IBulkImport: /

Я могу получить мой первичный ключ достаточно просто: -

public virtual string GetPrimaryKey(Type entityModelType)
{
    return _oltpContext.Model
        .FindEntityType(entityModelType)
        .FindPrimaryKey().Properties
        .Select(x => x.Name).Single();
}

Я нашел множество примеров, касающихся создания методов расширения, позволяющих передавать порядок по столбцам в виде строки, но все они в какой-то момент полагаются на Тип generi c передается с указанием типа.

Я нашел следующий пример: -

public static IQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string orderByProperty,
                          bool desc) 
{
     string command = desc ? "OrderByDescending" : "OrderBy";
     var type = typeof(TEntity);
     var property = type.GetProperty(orderByProperty);
     var parameter = Expression.Parameter(type, "p");
     var propertyAccess = Expression.MakeMemberAccess(parameter, property);
     var orderByExpression = Expression.Lambda(propertyAccess, parameter);
     var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType },
                                   source.Expression, Expression.Quote(orderByExpression));
     return source.Provider.CreateQuery<TEntity>(resultExpression);
}

, но, как вы видите, мне нужно снова передать тип TEntity. Я думаю, что приведение к IBulkImport - это то место, где начинаются мои проблемы, но я не могу понять, как построить оператор LINQ, который выбирает, ЗАКАЗЫВАЕТ, ВЫБРАЕТ и ВЫБИРАЕТ, когда все, что мне нужно для начала, это тип модели, т.е. TblProxyCompany в качестве параметра против пользовательский атрибут BulkImport.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...