C
C#9mo ago
UltraWelfare

❔ EFCore Expression Reuse Translations`

I have the following piece of projector:
public static Expression<Func<Order, OrderModel>> ProjectToOrderModel()
{
return order => new OrderModel
{
Uid = order.Uid,
Table = ProjectToOrderTable(order.Table),
};
}

public static TableModel ProjectToOrderTableModel(Table table) => new()
{
Id = table.Id,
Name = table.Name
};
public static Expression<Func<Order, OrderModel>> ProjectToOrderModel()
{
return order => new OrderModel
{
Uid = order.Uid,
Table = ProjectToOrderTable(order.Table),
};
}

public static TableModel ProjectToOrderTableModel(Table table) => new()
{
Id = table.Id,
Name = table.Name
};
Where Order is the EFCore entity and OrderModel is a POCO. Whenever I do the following : db.Orders.Select(Mapper.ProjectToOrderModel()) The correct SQL is generated by using the projection fields and not querying the whole columns. This surprised me because ProjectToOrderTableModel is a function and not an expression. However things get confusing when we get into lists. Rewriting the above snippet trying to include a nested collection
public static Expression<Func<Order, OrderModel>> ProjectToOrderModel()
{
return order => new OrderModel
{
Uid = order.Uid,
Table = ProjectToOrderTable(order.Table),
Items = order.OrderItems.AsQueryable().Select(MapToOrderItemsModel).ToList(),
};
}

public static TableModel ProjectToOrderTableModel(Table table) => new()
{
Id = table.Id,
Name = table.Name
};

public static OrderItemModel MapToOrderItemsModel(OrderItem i)
{
return new()
{
Uid = i.Uid,
Name = i.Title,
Price = i.Price
};
}
public static Expression<Func<Order, OrderModel>> ProjectToOrderModel()
{
return order => new OrderModel
{
Uid = order.Uid,
Table = ProjectToOrderTable(order.Table),
Items = order.OrderItems.AsQueryable().Select(MapToOrderItemsModel).ToList(),
};
}

public static TableModel ProjectToOrderTableModel(Table table) => new()
{
Id = table.Id,
Name = table.Name
};

public static OrderItemModel MapToOrderItemsModel(OrderItem i)
{
return new()
{
Uid = i.Uid,
Name = i.Title,
Price = i.Price
};
}
This fails because the Expression of type System.Func cannot be translated, which makes sense. I cannot understand how it works for a singular model, but it cannot work on a collection... ? Is there any tracking bug, or is it a forbidden thing to do?! P.S: I'm aware of the solution of implementing a public static Expression<Func<OrderItem, OrderItemModel>>, I just don't understand why the above doesn't work
9 Replies
Angius
Angius9mo ago
The above doesn't work, because it's a Func not an Expression
UltraWelfare
UltraWelfare9mo ago
My question was why a function worked in the table but not inside the list turns out, the function is called on the table, but in the select statement is just registered
UltraWelfare
UltraWelfare9mo ago
Stack Overflow
EFCore 7 reusable expression translation issues on collections
I have the following piece of projector: public static Expression<Func<Order, OrderModel>> ProjectToOrderModel() { return order => new OrderModel { Ui...
UltraWelfare
UltraWelfare9mo ago
I'm a bit worried about this particular comment https://stackoverflow.com/questions/77279017/efcore-7-reusable-expression-translation-issues-on-collections#comment136239711_77279017 If anyone has any recommendations, I'll happily hear
Angius
Angius9mo ago
Idk, I just use expressions, haven't used automapper in a while
UltraWelfare
UltraWelfare9mo ago
Yeah I've used it and I don't like the profiles the dependency injection you have to do + the reflection that it does in the background I'd rather just handwrite them.. Especially when the field names are not 1-1... In that case I'd write more code and still end up manually mapping the fields lol
Angius
Angius9mo ago
You can at least shorten your
public static Expression<Func<Order, OrderModel>> ProjectToOrderModel()
{
return order => new OrderModel
{
Uid = order.Uid,
Table = ProjectToOrderTable(order.Table),
Items = order.OrderItems.AsQueryable().Select(MapToOrderItemsModel).ToList(),
};
}
public static Expression<Func<Order, OrderModel>> ProjectToOrderModel()
{
return order => new OrderModel
{
Uid = order.Uid,
Table = ProjectToOrderTable(order.Table),
Items = order.OrderItems.AsQueryable().Select(MapToOrderItemsModel).ToList(),
};
}
to
public static Expression<Func<Order, OrderModel>> ProjectToOrderModel = (order) => new OrderModel
{
Uid = order.Uid,
Table = ProjectToOrderTable(order.Table),
Items = order.OrderItems.AsQueryable().Select(MapToOrderItemsModel).ToList(),
};
public static Expression<Func<Order, OrderModel>> ProjectToOrderModel = (order) => new OrderModel
{
Uid = order.Uid,
Table = ProjectToOrderTable(order.Table),
Items = order.OrderItems.AsQueryable().Select(MapToOrderItemsModel).ToList(),
};
UltraWelfare
UltraWelfare9mo ago
Actually in the snippet I posted in stackoverflow, I made it a property with only a { get; } But I totally understand what you mean
Accord
Accord9mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.