mirror of
				https://github.com/Biarity/Sieve.git
				synced 2025-11-04 02:39:00 +01:00 
			
		
		
		
	Merge pull request #26 from zolrath/Compare-Nullable
Allow comparing Nullable via Expression.Constant
This commit is contained in:
		@@ -142,7 +142,7 @@ namespace Sieve.Services
 | 
			
		||||
                                                  ? converter.ConvertFrom(filterTerm.Value)
 | 
			
		||||
                                                  : Convert.ChangeType(filterTerm.Value, property.PropertyType);
 | 
			
		||||
 | 
			
		||||
                        Expression filterValue = GetClosureOverConstant(constantVal);
 | 
			
		||||
                        Expression filterValue = GetClosureOverConstant(constantVal, property.PropertyType);
 | 
			
		||||
 | 
			
		||||
                        dynamic propertyValue = Expression.PropertyOrField(parameterExpression, property.Name);
 | 
			
		||||
 | 
			
		||||
@@ -219,12 +219,13 @@ namespace Sieve.Services
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //Workaround to ensure that the filter value gets passed as a parameter in generated SQL from EF Core
 | 
			
		||||
        //See https://github.com/aspnet/EntityFrameworkCore/issues/3361
 | 
			
		||||
        private Expression GetClosureOverConstant<T>(T constant)
 | 
			
		||||
        // Workaround to ensure that the filter value gets passed as a parameter in generated SQL from EF Core
 | 
			
		||||
        // See https://github.com/aspnet/EntityFrameworkCore/issues/3361
 | 
			
		||||
        // Expression.Constant passed the target type to allow Nullable comparison
 | 
			
		||||
        // See http://bradwilson.typepad.com/blog/2008/07/creating-nullab.html
 | 
			
		||||
        private Expression GetClosureOverConstant<T>(T constant, Type targetType)
 | 
			
		||||
        {
 | 
			
		||||
            Expression<Func<T>> closure = () => constant;
 | 
			
		||||
            return closure.Body;
 | 
			
		||||
            return Expression.Constant(constant, targetType);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private IQueryable<TEntity> ApplySorting<TEntity>(
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System;
 | 
			
		||||
using System.ComponentModel.DataAnnotations.Schema;
 | 
			
		||||
using Sieve.Attributes;
 | 
			
		||||
 | 
			
		||||
@@ -14,6 +14,7 @@ namespace SieveTests.Entities
 | 
			
		||||
        [Sieve(CanFilter = true, CanSort = true)]
 | 
			
		||||
        public int LikeCount { get; set; } = new Random().Next(0, 1000);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        [Sieve(CanFilter = true, CanSort = true)]
 | 
			
		||||
        public int CommentCount { get; set; } = new Random().Next(0, 1000);
 | 
			
		||||
 | 
			
		||||
@@ -23,5 +24,8 @@ namespace SieveTests.Entities
 | 
			
		||||
        [Sieve(CanFilter = true, CanSort = true)]
 | 
			
		||||
        [Column(TypeName = "datetime")]
 | 
			
		||||
        public DateTime DateLastViewed { get; set; } = DateTime.UtcNow;
 | 
			
		||||
 | 
			
		||||
        [Sieve(CanFilter = true, CanSort = true)]
 | 
			
		||||
        public int? CategoryId { get; set; } = new Random().Next(0, 4);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,8 @@ namespace SieveTests.Migrations
 | 
			
		||||
                    CommentCount = table.Column<int>(nullable: false),
 | 
			
		||||
                    DateCreated = table.Column<DateTimeOffset>(nullable: false),
 | 
			
		||||
                    LikeCount = table.Column<int>(nullable: false),
 | 
			
		||||
                    Title = table.Column<string>(nullable: true)
 | 
			
		||||
                    Title = table.Column<string>(nullable: true),
 | 
			
		||||
                    CategoryId = table.Column<int>(nullable: true)
 | 
			
		||||
                },
 | 
			
		||||
                constraints: table => table.PrimaryKey("PK_Posts", x => x.Id));
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,8 @@ namespace SieveTests.Migrations
 | 
			
		||||
 | 
			
		||||
                    b.Property<int>("LikeCount");
 | 
			
		||||
 | 
			
		||||
                    b.Property<int?>("CategoryId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Title");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,9 @@ namespace SieveUnitTests.Entities
 | 
			
		||||
        [Sieve(CanFilter = true, CanSort = true)]
 | 
			
		||||
        public DateTimeOffset DateCreated { get; set; } = DateTimeOffset.UtcNow;
 | 
			
		||||
 | 
			
		||||
        [Sieve(CanFilter = true, CanSort = true)]
 | 
			
		||||
        public int? CategoryId { get; set; } = new Random().Next(0, 4);
 | 
			
		||||
 | 
			
		||||
        [Sieve(CanFilter = true, CanSort = true)]
 | 
			
		||||
        public bool IsDraft { get; set; }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
 | 
			
		||||
@@ -28,24 +28,28 @@ namespace SieveUnitTests
 | 
			
		||||
                    Id = 0,
 | 
			
		||||
                    Title = "A",
 | 
			
		||||
                    LikeCount = 100,
 | 
			
		||||
                    IsDraft = true
 | 
			
		||||
                    IsDraft = true,
 | 
			
		||||
                    CategoryId = null,
 | 
			
		||||
                },
 | 
			
		||||
                new Post() {
 | 
			
		||||
                    Id = 1,
 | 
			
		||||
                    Title = "B",
 | 
			
		||||
                    LikeCount = 50,
 | 
			
		||||
                    IsDraft = false
 | 
			
		||||
                    IsDraft = false,
 | 
			
		||||
                    CategoryId = 1,
 | 
			
		||||
                },
 | 
			
		||||
                new Post() {
 | 
			
		||||
                    Id = 2,
 | 
			
		||||
                    Title = "C",
 | 
			
		||||
                    LikeCount = 0
 | 
			
		||||
                    LikeCount = 0,
 | 
			
		||||
                    CategoryId = 1,
 | 
			
		||||
                },
 | 
			
		||||
                new Post() {
 | 
			
		||||
                    Id = 3,
 | 
			
		||||
                    Title = "D",
 | 
			
		||||
                    LikeCount = 3,
 | 
			
		||||
                    IsDraft = true
 | 
			
		||||
                    IsDraft = true,
 | 
			
		||||
                    CategoryId = 2,
 | 
			
		||||
                },
 | 
			
		||||
            }.AsQueryable();
 | 
			
		||||
        }
 | 
			
		||||
@@ -103,6 +107,19 @@ namespace SieveUnitTests
 | 
			
		||||
            Assert.AreEqual(result.First().Id, 0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [TestMethod]
 | 
			
		||||
        public void CanFilterNullableInts()
 | 
			
		||||
        {
 | 
			
		||||
            var model = new SieveModel()
 | 
			
		||||
            {
 | 
			
		||||
                Filters = "CategoryId==1"
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            var result = _processor.Apply(model, _posts);
 | 
			
		||||
 | 
			
		||||
            Assert.IsTrue(result.Count() == 2);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [TestMethod]
 | 
			
		||||
        public void EqualsDoesntFailWithNonStringTypes()
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user