Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/AutoMapper/Mappers/ExpressionMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,16 @@ protected override Expression VisitBinary(BinaryExpression node)
var newLeft = Visit(node.Left);
var newRight = Visit(node.Right);

if (newLeft.Type != newRight.Type && newRight.Type == typeof(string))
// check if the non-string expression is a null constent
// as this would lead to a "null.ToString()" and thus an error when executing the expression
if (newLeft.Type != newRight.Type && newRight.Type == typeof(string) && !IsNullConstant(newLeft))
newLeft = Call(newLeft, typeof(object).GetDeclaredMethod("ToString"));
if (newRight.Type != newLeft.Type && newLeft.Type == typeof(string))
if (newRight.Type != newLeft.Type && newLeft.Type == typeof(string) && !IsNullConstant(newRight))
newRight = Call(newRight, typeof(object).GetDeclaredMethod("ToString"));
CheckNullableToNonNullableChanges(node.Left, node.Right, ref newLeft, ref newRight);
CheckNullableToNonNullableChanges(node.Right, node.Left, ref newRight, ref newLeft);
return MakeBinary(node.NodeType, newLeft, newRight);
bool IsNullConstant(Expression expression) => expression is ConstantExpression constant && constant.Value == null;
}

private static void CheckNullableToNonNullableChanges(Expression left, Expression right, ref Expression newLeft, ref Expression newRight)
Expand Down
48 changes: 35 additions & 13 deletions src/AutoMapperSamples.EF/EffortQueryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ namespace AutoMapperSamples.EF
[TestFixture]
public class EffortQueryTests
{
private Mapper _mapper;
private MapperConfiguration _config;

static EffortQueryTests()
{
Effort.Provider.EffortProviderConfiguration.RegisterProvider();
Expand All @@ -23,7 +26,10 @@ static EffortQueryTests()
[SetUp]
public void SetUp()
{
Mapper.Initialize(MappingConfiguration.Configure);
//Mapper.Initialize(MappingConfiguration.Configure);

_config = new MapperConfiguration(MappingConfiguration.Configure);
_mapper = new Mapper(_config);
}

[Test]
Expand All @@ -34,8 +40,8 @@ public void Effort_FilterByDto()
IQueryable<OrderDto> sourceResult = new OrderDto[0]
.AsQueryable()
.Where(s => s.FullName.EndsWith("Bestellung"))
.Map<OrderDto, Order>(context.OrderSet)
.ProjectTo<OrderDto>(); // projection added
.Map<OrderDto, Order>(context.OrderSet, _config)
.ProjectTo<OrderDto>(_config); // projection added

var dtos = sourceResult.ToList();

Expand All @@ -54,8 +60,8 @@ public void Effort_FilterByMappedQuery()
IQueryable<OrderDto> sourceResult = new OrderDto[0]
.AsQueryable()
.Where(s => s.FullName.EndsWith("Bestellung"))
.Map<OrderDto, Order>(context.OrderSet)
.ProjectTo<OrderDto>(); // projection added
.Map<OrderDto, Order>(context.OrderSet, _config)
.ProjectTo<OrderDto>(_config); // projection added
var dtos = sourceResult.ToList();
Assert.AreEqual(2, dtos.Count);

Expand All @@ -70,8 +76,8 @@ public void Effort_FilterByMappedQuery()
{
IQueryable<OrderDto> sourceResult2 = new OrderDto[0]
.AsQueryable()
.Map<OrderDto, Order>(context.OrderSet)
.ProjectTo<OrderDto>(); // projection added
.Map<OrderDto, Order>(context.OrderSet, _config)
.ProjectTo<OrderDto>(_config); // projection added
var dtos2 = sourceResult
.Where(s => s.FullName.EndsWith("Bestellung"))
.ToList();
Expand All @@ -81,9 +87,9 @@ public void Effort_FilterByMappedQuery()
catch (NotSupportedException)
{
}

// Using "AsDataSource"
IQueryable<OrderDto> sourceResult4 = context.OrderSet.UseAsDataSource(Mapper.Configuration).For<OrderDto>();
IQueryable<OrderDto> sourceResult4 = context.OrderSet.UseAsDataSource(_config).For<OrderDto>();
var dtos4 = sourceResult4.Where(d => d.FullName.EndsWith("Bestellung")).ToList();

Assert.AreEqual(2, dtos4.Count);
Expand All @@ -97,7 +103,7 @@ public void Effort_FilterByMappedQuery_InnerQueryOrderedAndFiltered()
{
var orders = context.OrderSet.Where(o => o.Price > 85D).OrderBy(o => o.Price);

IQueryable<OrderDto> lazilyMappedQuery = orders.UseAsDataSource(Mapper.Configuration).For<OrderDto>();
IQueryable<OrderDto> lazilyMappedQuery = orders.UseAsDataSource(_mapper).For<OrderDto>();
var dtos3 = lazilyMappedQuery
.Where(d => d.FullName.EndsWith("Bestellung")).ToList();

Expand All @@ -112,7 +118,7 @@ public void Effort_OrderByDto_FullName()
{
var orders = context.OrderSet;

IQueryable<OrderDto> lazilyMappedQuery = orders.UseAsDataSource(Mapper.Configuration).For<OrderDto>();
IQueryable<OrderDto> lazilyMappedQuery = orders.UseAsDataSource(_mapper).For<OrderDto>();
var dtos3 = lazilyMappedQuery
.OrderBy(dto => dto.FullName).Skip(2).ToList();

Expand All @@ -121,14 +127,30 @@ public void Effort_OrderByDto_FullName()
}
}

[Test]
public void Effort_FilterByDto_FullName_Contains()
{
using (var context = new TestDbContext(Effort.DbConnectionFactory.CreateTransient()))
{
var orders = context.OrderSet;

IQueryable<OrderDto> lazilyMappedQuery = orders.UseAsDataSource(_mapper).For<OrderDto>();
var dtos3 = lazilyMappedQuery
.Where(dto => dto.FullName.Contains("Zalando")).ToList();

Assert.AreEqual(1, dtos3.Count);
Assert.AreEqual("Zalando Bestellung", dtos3.Single().FullName);
}
}

[Test]
public void Effort_OrderByDto_Price()
{
using (var context = new TestDbContext(Effort.DbConnectionFactory.CreateTransient()))
{
var orders = context.OrderSet;

IQueryable<OrderDto> lazilyMappedQuery = orders.UseAsDataSource(Mapper.Configuration).For<OrderDto>();
IQueryable<OrderDto> lazilyMappedQuery = orders.UseAsDataSource(_mapper).For<OrderDto>();
var dtos3 = lazilyMappedQuery
.OrderBy(dto => dto.Price).Skip(2).ToList();

Expand All @@ -144,7 +166,7 @@ public void Effort_FilterByMappedQuery_SkipAndTake()
{
var orders = context.OrderSet.OrderBy(o => o.Name);

IQueryable<OrderDto> lazilyMappedQuery = orders.UseAsDataSource(Mapper.Configuration).For<OrderDto>();
IQueryable<OrderDto> lazilyMappedQuery = orders.UseAsDataSource(_mapper).For<OrderDto>();
var dtos3 = lazilyMappedQuery
.Skip(1).Take(1).ToList();

Expand Down
4 changes: 2 additions & 2 deletions src/AutoMapperSamples.OData/ODataQueryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public virtual void SetUp()
// Start OWIN host
_webApp = WebApp.Start<Startup>(url: _baseAddress);
}

[TearDown]
public virtual void TearDown()
{
Expand Down Expand Up @@ -325,7 +325,7 @@ public void CanFilter_OrderDateGt()

// Act
var response = client.GetAsync(_baseAddress + "api/Orders?$filter=OrderDate gt DateTime'2015-02-01T00:00:00'").Result;

// Assert
Console.WriteLine(response);
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
Expand Down
15 changes: 9 additions & 6 deletions src/AutoMapperSamples.OData/OrdersController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,22 @@ namespace AutoMapperSamples.OData
public class OrdersController : ApiController
{
private TestDbContext context = null;
private MapperConfiguration _config;
private Mapper _mapper;
internal static Action<Exception> OnException { get; set; }

public OrdersController()
{
Mapper.Initialize(MappingConfiguration.Configure);
_config = new MapperConfiguration(MappingConfiguration.Configure);
_mapper = new Mapper(_config);

context = new TestDbContext(Effort.DbConnectionFactory.CreateTransient());
}

[EnableQuery]
public IQueryable<OrderDto> Get()
{
return context.OrderSet.Include("Customer").UseAsDataSource(Mapper.Instance)
return context.OrderSet.Include("Customer").UseAsDataSource(_mapper)
// add an optional exceptionhandler that will be invoked
// in case an exception is raised upon query execution.
// otherwise it would get lost on the WebApi side and all we would get would be
Expand All @@ -53,10 +56,10 @@ public IQueryable<OrderDto> Get()
var customerIds = enumerator.OfType<OrderDto>().Select(o => o.Customer.Id);
// add IDs of orders
var customersOrders = context.CustomerSet
.Include("Orders")
.Where(c => customerIds.Contains(c.Id))
.Select(c => new { CustomerId = c.Id, OrderIds = c.Orders.Select(o => o.Id) })
.ToDictionary(c => c.CustomerId);
.Include("Orders")
.Where(c => customerIds.Contains(c.Id))
.Select(c => new { CustomerId = c.Id, OrderIds = c.Orders.Select(o => o.Id) })
.ToDictionary(c => c.CustomerId);
// apply the list of IDs to each OrderDto
foreach (var order in enumerator.OfType<OrderDto>())
{
Expand Down