我正在为添加,删除和查找实现泛型,因为我正在实现多租户,这使我可以从数据库访问IQueryables,而不是DbSets。
如何实施添加:
之前的代码:
interest = db.Interests.Add(new Interest()) // Interests is dbSet
之后的代码:
interest = db.Add(new Interest()) // Interests is dbSet
// in db class
public T Add<T>(T item) where T : class, ITenantData
{
var set = _appContext.Set<T>();
return set.Add(item);
}
这很有效。现在我正在尝试为Find做同样的事情,但因为我正在使用Id而不是Typed参数,所以我有点卡住了。
之前的代码:
var aptitude = db.Aptitudes.Find(interest.AptitudeId); // Aptitudes is a DbSet
之后的代码:
var aptitude = db.Find(interest.AptitudeId); // how to identify type?
我不能这样做:
var aptitude = db.Aptitudes.Find(interest.AptitudeId);
因为Aptitudes现在是一个IQueryable。
所以这目前失败了:
public T Find<T>(T query) where T : class, ITenantData
{
var set = _mentorContext.Set<T>();
return set.Find(query);
}
因为没有识别出类型 - 我得到:
类型'int'必须是引用类型才能将其用作 泛型类型或方法中的参数'T' 'App.Context.TenantContext.Find(T)'Service.cs
我对仿制药有点新意,这里的任何帮助都会非常感激。
答案 0 :(得分:1)
使用扩展方法解决此问题。
public IQueryable<T> Query<T>() where T : class, ITenantData
{
return _mentorContext.Set<T>().AsNoTracking();
}
......同时在另一堂课......
public static MentorContextExtensions
{
public static InterestEntity ByAptitudeId(
this IQueryable<InterestEntity> queryable,
int aptitudeId)
{
return queryable.SingleOrDefault(x => x.AptitudeId == aptitudeId);
}
}
...针对IQueryable<T>
...
db.Query<InterestEntity>().ByAptitudeId(interest.AptitudeId);
上面的示例返回SingleOrDefault
,但您可以使用IQueryables
,IEnumerables
轻松返回集合(预先过滤的.Where
或bool
)使用.Any
等
要在.Find
上保持IDbSet
(按主键)方法的使用,您可以这样做:
public T Find<T>(params object[] keyComponents) where T : class, ITenantData
{
return _mentorContext.Set<T>().Find(keyComponents);
}
...并像这样使用它......
var aptitude = db.Find<Aptitude>(interest.AptitudeId);
...也就是说,使用.Find
在使用某种突变代码进行插入,更新,删除实体时可能会更快。 .Find
将始终将实体附加到上下文,这是您需要变更数据时所需的内容。但是,您无法在其上调用.AsNoTracking()
,因为它返回单个实体。如果您只需要实体读取其属性或用于显示目的,.AsNoTracking
将使整个实体图(实体及其导航/集合属性)与上下文分离,这可能比使用{{1更快}}。如果您以后想要在变异代码中使用相同的实体实例,那么您可以在那时将它附加到上下文。