我创建了一个 API,其中我在数据库中有多个对象(例如卖家、产品等),并且我为这些对象中的每一个提供了一个 enpoint api 以使用其 Id 从数据库中获取给定对象(始终为Guid 类型)。我注意到在我处理业务逻辑的每个类中,我都重复相同的代码:
//GetOneSellerQueryHandler class
...
var sellerDbItem = await Context.Seller.Where(x => x.Id == request.Id)
.SingleOrDefaultAsync();
var seller = Mapper.Map<SellerDto>(sellerDbItem );
...
//GetOneProductQueryHandler class
...
var productDbItem = await Context.Product.Where(x => x.Id == request.Id)
.SingleOrDefaultAsync();
var product = Mapper.Map<ProductDto>(productDbItem);
...
使用泛型方法创建抽象类以通过传递的 id 从 db 获取元素是否有意义?
另外,这个泛型方法的实现是否正确?
//Abstract class
public async Task<F> GetElementById<T,F>(T obj, Guid id) where T : class
{
T dbItem = (T) Convert.ChangeType(obj switch
{
Seller => await Context.Seller.Where(x => x.Id == id).SingleAsync(),
Product=> await Context.Product.Where(x => x.Id == id).SingleAsync(),
_=>throw new NotImplementedException()
}, typeof(T));
return Mapper.Map<F>(dbItem);
}
//GetOneProductQueryHandler class
...
var productDbItem = await GetElementById<Product, ProductDto>(new Product(), request.Id)
...
//GetOneSellerQueryHandler class
...
var sellerDbItem = await GetElementById<Seller, SellerDto>(new Seller(), request.Id)
...
最佳答案
Does it make sense create abstract class with generic method to get element from db by passed id?
我的建议:不要害怕重复自己。
通用减少了行数......但它会损害可维护性。
Moreover, is this implementation of the generic method correct?
不完全是,因为类型是硬编码的。此外,过滤 Context.XXX.Where(x => x.Id == id).SingleAsync()
的代码是重复的。这结合了所有默认值、更多的行和更少的可维护性。
EF Core 使用Queryable
,然后您可以生成一个通用表达式,例如:
public static class QueryableExtensions
{
public static Task<T>? GetById<T>(this IQueryable<T> query, Guid id)
{
// This expression is lambad : e => e.Id == id
var parameter = Expression.Parameter(typeof(T));
var left = Expression.Property(parameter, "Id");
var right = Expression.Constant(id);
var equal = Expression.Equal(left, right);
var byId = Expression.Lambda<Func<T, bool>>(equal, parameter);
return query.SingleAsync(byId);
}
}
//Use
var seller = await context.Sellers.GetById(Guid.NewGuid());
var product = await context.Products.GetById(Guid.NewGuid());
表达力很强,但很难。
关于c# - 使用 EF Core 按 Id 检索实体的通用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71806522/