我創建了一個 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)
...
uj5u.com熱心網友回復:
使用通用方法創建抽象類以通過傳遞的 id 從 db 獲取元素是否有意義?
我的建議:不要害怕重復自己。
通用減少行數......但它會損害可維護性。
此外,通用方法的這種實作是否正確?
不完全是,因為型別是硬編碼的。而且過濾的代碼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());
表達很強大,但很難。
uj5u.com熱心網友回復:
通常我為資料庫物體宣告基類/介面以訪問共享屬性并基于它們創建通用方法
using AutoMapper;
using Microsoft.EntityFrameworkCore;
public interface IEntity
{
public Guid Id { get; set; }
}
public class Seller : IEntity
{
public Guid Id { get; set; }
}
public class Product : IEntity
{
public Guid Id { get; set; }
}
public class ApplicationDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<Seller> Sellers { get; set; }
}
public class Repository
{
private readonly ApplicationDbContext ctx;
public Repository(ApplicationDbContext ctx)
{
this.ctx = ctx;
}
public Task<T> GetById<T>(Guid id) where T : class, IEntity
{
return ctx.Set<T>().SingleAsync<T>(x => x.Id == id);
}
}
public class Handler<Entity, Dto> where Entity : class, IEntity
{
private readonly Repository repository;
private readonly IMapper mapper;
public Handler(Repository repository, IMapper mapper)
{
this.repository = repository;
this.mapper = mapper;
}
public async Task<Dto> GetDtoById(Guid id)
{
var entity = await repository.GetById<Entity>(id);
var dto = mapper.Map<Dto>(entity);
return dto;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/461440.html
