C# generics for DbSet<something>
本文关键字:something gt generics lt DbSet for | 更新日期: 2023-09-27 18:16:56
我有各种方法,应该能够调用传递DbSet作为参数的泛型方法。目前我有这样的工作代码(这里显示的是简化后的):
public class MyClass
{
private async Task<JsonResult> Delete<T>(int? id, T dbs) where T : DbSet<A>
{
var row = await dbs.SingleOrDefaultAsync(m => m.ID == id);
dbs.Remove(row);
await db.SaveChangesAsync();
return Json(r); // definition od "r" removed from code to simplify it
}
public async Task<JsonResult> A(int? id)
{
return await Delete(id, db.A);
}
public async Task<JsonResult> B(int? id)
{
return await Delete(id, db.B);
}
public async Task<JsonResult> C(int? id)
{
return await Delete(id, db.C);
}
我不知道如何修改"Delete"方法的签名,以便方法A,B,C…
由于在Delete中引用ID字段,因此需要引入一些接口,如
interface IHasID {
int ID { get; }
}
那么您需要为所有具有ID的实体实现该接口(在部分类中)。然后你可以像这样修改Delete
private async Task<JsonResult> Delete<T>(int? id, DbSet<T> dbs) where T : class, IHasID {
var row = await dbs.SingleOrDefaultAsync(m => m.ID == id);
dbs.Remove(row);
await db.SaveChangesAsync();
return Json(r); // definition od "r" removed from code to simplify it
}
并像这样使用(假设A实现了IHasID):
public async Task<JsonResult> A(int? id) {
return await Delete(id, db.As);
}
如果你不想为每个实体实现IHasID
(虽然这很容易,因为ID属性已经存在于你的实体),有可能没有接口(虽然不太安全,因为你将能够传递任何实体到这个Delete方法,你不会发现错误,直到运行时):
private async Task<JsonResult> Delete<T>(int? id, DbSet<T> dbs) where T : class
{
var parameter = Expression.Parameter(typeof(T), "entity");
// generate expression entity => entity.ID = id
var condition = (Expression<Func<T, bool>>) Expression.Lambda(
Expression.Equal(
Expression.Property(parameter, "ID"),
Expression.Constant(id)
)
, parameter);
var row = await dbs.SingleOrDefaultAsync(condition);
dbs.Remove(row);
await db.SaveChangesAsync();
return Json(r);
}