我正在重构应用程序以反转一些依赖项。部分原始代码用于DbContext.Set<MyEntityType>()
获取要查询的集合。
通过反转,使用 MyEntityType 的代码不再明确知道DbContext.Set<MyEntityType>()
,所以现在我正在使用DbContext.Set(TypeVariable)
。
重构在返回正确 DbSet 的范围内起作用。
但是,类型DbContext.Set(TypeVariable).Local
是IList
(包含类型未知) where-as 的DbContext.Set<MyEntityType>().Local
类型ObservableCollection<MyEntityType>
。这意味着现在不可能针对 DbSet 执行 Linq。
我能够实现的最佳解决方法是转换为 MyEntityType 和其他实体类型实现的接口(为清楚起见省略了一些代码)
var set = Context.Set(targetType);
var entity = set.Local.OfType<IActionTarget>()
.FirstOrDefault(l => l.Id == key.Id && l.EffectiveDate == key.EffectiveDate);
var querables = set as IQueryable<IActionTarget>;
entity = querables.FirstOrDefault(e => e.Id == key.Id && e.EffectiveDate == key.EffectiveDate);
所以,两个问题:
为什么不DbContext.Set(TypeVariable)
返回强类型集?
有没有更好的方法来进行依赖倒置?
根据要求提供一些进一步的细节
这都是关于依赖关系的。模型包含 POCO 类,这些类通过 EF Code First 以典型方式(但通过Repository)持久化。ActionEvaluator获取一些传入数据,并通过Repository 方法确定需要发生的操作 - 因此是针对 DbSet 的查询。
在原始代码中,只有一种类型的传入数据(特定格式的 CSV),并且 ActionEvaluator 对这些数据有紧密的依赖关系,并且知道哪些 POCO 类适用于哪些 CSV 记录。
现在,我们要扩展以使用不同的 CSV 格式和 Web api 消息。为此,我们需要反转依赖关系,以便DataSource告诉 ActionEvaluator 它的记录适用于哪些 POCO 类。这是通过类型变量完成的。
因此,ActionEvaluator 不能再使用泛型类型参数,但它可以将类型变量传递给 Repository,Repository 使用它来查找正确的 DbSet。
问题是找到 DbSet 的两种方法之间的区别 -DbContext.Set<AnEntity>()
和DbContext.Set(TypeVariable)
.
我想我要求增强 EF 以使这两个函数的返回值在功能上等效,但这可能是不可能的,因为第二个版本的类型是在运行时确定的。
这是所要求的完整方法代码:
private IActionTarget DbContextGetEntity(Type targetType, IActionTarget key)
{
var set = Context.Set(targetType);
if (set == null)
{
throw new Exception("Unable to find DbSet for type '{0}'".F(targetType.Name));
}
// Look in the local cache first
var entity = set.Local.OfType<IActionTarget>()
.FirstOrDefault(l => l.Id == key.Id && l.EffectiveDate == key.EffectiveDate);
if (entity == null)
{
// If not found locally, hit the database
var querables = set as IQueryable<IActionTarget>;
if (querables != null)
{
entity = querables.FirstOrDefault(e => e.Id == key.Id && e.EffectiveDate == key.EffectiveDate);
}
}
return entity;
}
理想情况下,我想更换
var entity = set.Local.OfType<IActionTarget>()
.FirstOrDefault(l => l.Id == key.Id && l.EffectiveDate == key.EffectiveDate);
和
var entity = set.Local.OfType(targetType)
.FirstOrDefault(l => l.Id == key.Id && l.EffectiveDate == key.EffectiveDate);