使用.net-6和EF Core 6,我希望使用表达式定义可重用的投影,以便可以将DTOMap集中在一个位置。
给定具有关系的实体:
class Property {
public int Id {get; set;}
public List<Amenity> Amenities {get; set;}
public Address Address {get; set;}
}
class Amenity {
public int Id {get; set;}
public string Name {get; set;}
public string Value {get; set;}
}
class Address {
public int Id {get; set;}
public string Country {get; set;}
public string City {get; set;}
public string Street {get; set;}
}
他们的DTO:
class PropertyDto {
public int Id {get; set;}
public List<AmenityDto> Amenities {get; set;}
public AddressDto Address {get; set;}
}
class AmenityDto{
public int Id {get; set;}
public string Name {get; set;}
public string Value {get; set;}
}
class AddressDto{
public int Id {get; set;}
public string Country {get; set;}
public string City {get; set;}
public string Street {get; set;}
}
我可以创建一个可重用的投影表达式:
public class PropertyDto {
...
public static Expression<Func<Property, PropertyDto>> Projection =
property => new PropertyDto{
Id = property.Id,
};
...
}
我可以在任何查询的Select()
调用中使用它作为投影表达式,EF将“访问”它并将其转换为SQL,以便只获取我需要的那些列:
DbContext.Set<Property>()
.Select(Property.Projection)
.ToListAsync();
如果我想重用Amenities的投影,我可以为AmenityDto
创建一个投影表达式,并执行以下操作:
public static Expression<Func<Property, PropertyDto>> Projection =
property => new PropertyDto{
Id = property.Id,
Amenities = property.Amenities.AsQueryable().Select(Amenity.Dto).ToList(),
};
但是如果我想对Address
做同样的事情,我不能用.Select()
来投影它,因为它不是一个集合。
public static Expression<Func<Property, PropertyDto>> Projection =
property => new PropertyDto{
Id = property.Id,
Amenities = property.Amenities.AsQueryable().Select(Amenity.Dto).ToList(),
Address = // how can I use AddressDto.Projection here?
};
地址字段需要一个AddressDto。如果我使用回调,例如AddressDto.Projection(address)
EF将加载整个实体,因为它不能将方法转换为SQL。在搜索了很多次之后,我只看到一些文章讨论使用.AsExpandable()
或[ReplaceWithExpression]
属性来指示EF用表达式替换方法。据我所知,EF Core 6.0不再支持这些功能
在投影单个实体时,是否有任何方法可以重用投影表达式?
1条答案
按热度按时间j2cgzkjk1#
只是为了回答我自己的问题,并感谢@SvyatoslavDanyliv的评论,以下是我所做的来解决我的问题:
1.我安装了
LinqKit.Microsoft.EntityFrameworkCore
1.我创建了一个方法,该方法返回用于将领域模型投影到Dto等价物的表达式:
1.我创建了将从其他投影中调用的方法,LinqKit将用上面的投影表达式替换该方法。
我决定使用
throw new NotImplementedException()
,因为我只会从投影中调用此方法,但是如果您希望重用此方法在代码库中的其他位置创建DTO,则可以编译和调用投影。1.我在我的父EF投影中使用了可替换的Dto投影方法:
生成的EF SQL仅正确选择子Dto使用的那些列。