【发布时间】:2017-02-24 06:29:26
【问题描述】:
我正在尝试将我的组织使用的框架重写为 .Net Core;特别是此时的通用存储库。 我被困在以下问题上。
我们有一个 BaseEntity 定义如下:
public abstract class BaseEntity<T> : IBaseEntity<T>
{
[Key]
public virtual T Id { get; set; }
}
它继承自接口:
public interface IBaseEntity<T>
{
[Key]
T Id { get; set; }
}
我这样定义一个实体:
public class Employee : BaseEntity<int>
{
public string OfficeBureau { get; set; }
public string Supervisor { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Notes { get; set; }
// TODO:
// public virtual ICollection<Case> Cases { get; set; }
}
应用上下文:
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
public DbSet<Employee> Employees { get; set; }
}
回购接口:
public interface IGenericRepository<T>
where T : BaseEntity<T>
{
IQueryable<T> GetAll(); // No need to async IQueryable
Task<T> GetAsync(int id);
Task<T> InsertAsync(T entity);
Task UpdateAsync(T entity);
Task DeleteAsync(T entity);
#region Possible TODOs:
// Should this one go in the Service Layer?
// Task<IEnumerable<T>> FindBy(Expression<Func<T, bool>> predicate);
//Task AddRange(IEnumerable<T> entities);
//Task RemoveRange(IEnumerable<T> entities);
#endregion
Task SaveAsync();
}
回购实施:
public class GenericRepository<T> : IGenericRepository<T>
where T: BaseEntity<T>
{
private readonly ApplicationDbContext _context;
private DbSet<T> _entities;
public GenericRepository(ApplicationDbContext context)
{
_context = context;
_entities = context.Set<T>();
}
// No need to async IQueryable
public IQueryable<T> GetAll() => _entities.AsQueryable();
public Task<T> GetAsync(int id)
{
throw new NotImplementedException();
}
现在看看签名:
public Task<T> GetAsync(int id)
这是我的困境。 将所有实体设置为从 BaseEntity 继承,以便我们在此处搜索硬编码的 int 类型的 GetById 或 GetAsync 时可以动态获得 int 或 guid 的 id 有什么意义?
这是一种常见的模式吗?这是代码原作者的短板吗?还是我在这种模式中遗漏了什么?
如果这是一个缺点,有没有办法通过反射和搜索来动态获取实体 id 的类型?如果是这样,它会影响性能吗?
我是否应该只删除 BaseEntity 上 id 类型的泛型并强制框架的用户始终使所有实体在使用该框架的整个应用程序中具有相同类型的 ID?
除了通用回购的主要目的之外。不必为每个实体使用相同的方法编写 repo。 任何建议在这里表示赞赏。
【问题讨论】:
-
您的标题似乎与您的问题不匹配。
-
EntityFramework 团队自己处理了同样的问题,他们公开了
DbContext.Find()方法(实际上是“通过 id 获取”),该方法期望object id作为参数(参见 github.com/aspnet/EntityFramework/blob/dev/src/… )。 -
为了澄清 GenericRepo 中的 T 是否指的是 Employee,而 Employee 派生自 BaseEntity
其中 T 是实体 ID 的类型,那么我说 T 表示“Employee : BaseEntity”嵌套在 GenericRepository 中。这是两个不同的T。我玩弄了“GenericRepository 然后是 BaseEntity 。对于问题的命名感到抱歉。在查看上面的 EF 团队评论时,很有趣,但现在看到应用它或它将如何解决我的问题问题。 -
@Sam,当
id是object时,应用它的方式就是await return _entities.FindAynsc(id)。 -
我无法理解这一点。我是否必须更改上述任何代码?还是会按原样工作?
标签: c# generics asp.net-core-mvc