У меня есть требование работать с несколькими таблицами, которые необходимо синхронизировать / создать резервную копию. Все классы этих таблиц реализуют ITrackModifiedDate
:
interface ITrackModifiedDate
{
DateTime ModifiedDate { get; set; }
}
Мне нужно работать с этими партиями, а это значит, что мне нужно сделать закладку, где я последний раз занимался. Так что я могу сортировать по ModifiedDate
и просто отслеживать свои последние ModifiedDate
. Но в плане есть морщина: может случиться так, что несколько записей будут иметь одинаковые значения ModifiedDate
. Это означает, что мне нужен вторичный идентификатор, и единственное, на что я могу в общем полагаться, это ключевое поле, которое неизменно представляет собой Guid
.
Я получил некоторую помощь в Expression
материале от здесь , но когда я попытался переделать, чтобы добавить в предложение "больше чем", все сломалось.
async Task<ICollection<T>> GetModifiedRecords<T>(DateTime modifiedSince, Guid lastId) where T : class, ITrackModifiedDate
{
var parameterExp = Expression.Parameter(typeof(T), "x");
var propertyExp = Expression.Property(parameterExp, keyField);
var target = Expression.Constant(lastId);
var greaterThanMethod = Expression.GreaterThan(propertyExp, target);
var lambda = Expression.Lambda<Func<T, bool>>(greaterThanMethod, parameterExp);
var query = db.Set<T>()
.Where(t => t.ModifiedDate > modifiedSince ||
t.ModifiedDate == modifiedSince && lambda.Invoke(t));
var orderByExp = Expression.Lambda(propertyExp, parameterExp);
var thenByMethodGeneric = typeof(Queryable)
.GetMethods()
.Single(mi => mi.Name == "ThenBy" && mi.GetParameters().Length == 2);
var thenByMethod = thenByMethodGeneric.MakeGenericMethod(typeof(T), propertyExp.Type);
// first order by date, then id
query = query.OrderBy(t => t.ModifiedDate)
.AsQueryable();
query = (IQueryable<T>)thenByMethod.Invoke(null, new object[] { query, orderByExp });
return await query.ToListAsync();
}
Попытка выполнить этот запрос приводит к:
System.InvalidOperationException: бинарный оператор GreaterThan не определен для типов «System.Guid» и «System.Guid».
О, дорогой. Кажется, гидам, как и людям, не нравится, когда их сравнивают друг с другом. Либо так, либо я использую неправильное выражение сравнения.
Очевидное решение, которое приходит на ум - преобразовать Guid в строку для сравнения, но (а) это выглядит немного неэффективно, и (б) я не знаю, как написать Expression
, который преобразует Направляющий на строку.
Является ли преобразование в строку правильным способом? Если так, что Expression
сделает работу? Если нет, то каков правильный подход?