How to query Code First entities based on rowversion/timestamp value?

前端 未结 10 1149
忘了有多久
忘了有多久 2020-12-14 17:56

I\'ve run into a case where something that worked fairly well with LINQ to SQL seems to be very obtuse (or maybe impossible) with the Entity Framework. Specifically, I\'ve g

10条回答
  •  暖寄归人
    2020-12-14 18:32

    I extended jnm2’s answer to hide the ugly expression code in a extension method

    Usage:

    ctx.Foos.WhereVersionGreaterThan(r => r.RowVersion, myVersion);
    

    Extension Method:

    public static class RowVersionEfExtensions
    {
    
    
        private static readonly MethodInfo BinaryGreaterThanMethodInfo = typeof(RowVersionEfExtensions).GetMethod(nameof(BinaryGreaterThanMethod), BindingFlags.Static | BindingFlags.NonPublic);
        private static bool BinaryGreaterThanMethod(byte[] left, byte[] right)
        {
            throw new NotImplementedException();
        }
    
        private static readonly MethodInfo BinaryLessThanMethodInfo = typeof(RowVersionEfExtensions).GetMethod(nameof(BinaryLessThanMethod), BindingFlags.Static | BindingFlags.NonPublic);
        private static bool BinaryLessThanMethod(byte[] left, byte[] right)
        {
            throw new NotImplementedException();
        }
    
        /// 
        /// Filter the query to return only rows where the RowVersion is greater than the version specified
        /// 
        /// The query to filter
        /// Specifies the property of the row that contains the RowVersion
        /// The row version to compare against
        /// Rows where the RowVersion is greater than the version specified
        public static IQueryable WhereVersionGreaterThan(this IQueryable query, Expression> propertySelector, byte[] version)
        {
            var memberExpression = propertySelector.Body as MemberExpression;
            if (memberExpression == null) { throw new ArgumentException("Expression should be of form r=>r.RowVersion"); }
            var propName = memberExpression.Member.Name;
    
            var fooParam = Expression.Parameter(typeof(T));
            var recent = query.Where(Expression.Lambda>(
                Expression.GreaterThan(
                    Expression.Property(fooParam, propName),
                    Expression.Constant(version),
                    false,
                    BinaryGreaterThanMethodInfo),
                fooParam));
            return recent;
        }
    
    
        /// 
        /// Filter the query to return only rows where the RowVersion is less than the version specified
        /// 
        /// The query to filter
        /// Specifies the property of the row that contains the RowVersion
        /// The row version to compare against
        /// Rows where the RowVersion is less than the version specified
        public static IQueryable WhereVersionLessThan(this IQueryable query, Expression> propertySelector, byte[] version)
        {
            var memberExpression = propertySelector.Body as MemberExpression;
            if (memberExpression == null) { throw new ArgumentException("Expression should be of form r=>r.RowVersion"); }
            var propName = memberExpression.Member.Name;
    
            var fooParam = Expression.Parameter(typeof(T));
            var recent = query.Where(Expression.Lambda>(
                Expression.LessThan(
                    Expression.Property(fooParam, propName),
                    Expression.Constant(version),
                    false,
                    BinaryLessThanMethodInfo),
                fooParam));
            return recent;
        }
    
    
    
    }
    

提交回复
热议问题