我正在使用EF4和POCO并试图使其成为可测试的架构。 所以我创建了IObjectContext接口,如下所示:
public interface IObjectContext
{
IObjectSet<Employee> Employees { get; }
IObjectSet<Team> Teams { get; }
void Commit();
}
然后我在我真实的ObjectContext类中将属性类型更改为IObjectSet,如下所示:
public partial class HRManagementEntities : ObjectContext, IUnitOfWork
{
// skip some codes here...........
public IObjectSet<Employee> Employees
{
get { return _employees ?? (_employees = CreateObjectSet<Employee>("Employees"));
}
private IObjectSet<Employee> _employees;
public IObjectSet<Team> Teams
{
get { return _teams ?? (_teams = CreateObjectSet<Team>("Teams")); }
}
private IObjectSet<Team> _teams;
public void Commit()
{
SaveChanges();
}
}
在我的服务层中,按照以下方式使用EF:
public class Service
{
private IObjectContext ctx;
public HRService(IObjectContext ctx)
{
this.ctx = ctx;
}
public List<Team> GetAllTeams()
{
return ctx.Teams.ToList();
}
}
这是我的问题,如何调用ObjectContext中的方法,例如ApplyCurrentValues(),ExecuteStoreCommand()等等??
我是否需要在IObjectContext中实现这些方法才能使用?
修改
作为RPM的建议,我为ApplyCurrentValues()方法创建了以下扩展方法,另一种方法可以以相同的方式扩展。
public static T UpdateModel<T>(this IObjectSet<T> iObjectSet, T currentEntity) where T : class
{
ObjectSet<T> objectSet = iObjectSet as ObjectSet<T>;
if (objectSet == null || currentEntity == null)
throw new ArgumentNullException();
return objectSet.ApplyCurrentValues(currentEntity);
}
答案 0 :(得分:2)
您需要为所需方法创建扩展方法,并将IObjectSet
转换为ObjectSet
。
例如,如果您需要.Include
(急切加载),请使用此扩展方法:
public static IQueryable<TSource> Include<TSource>(this IQueryable<TSource> source, string path)
{
var objectQuery = source as ObjectQuery<TSource>;
if (objectQuery != null)
{
objectQuery.Include(path);
}
return source;
}
你可能可能为IObjectContext
做同样的事情,但不确定为什么你甚至嘲笑这个。您不应该将OC公开到存储库之外,只有存储库应该知道OC。
在您的示例中,您的服务正在实体/存储库上调用ctx.Teams。
IMO你的服务应该调用ctx.Find,这将是强类型(通过泛型)到Teams对象上下文。 (IRepository)
常见的陷阱是过度模仿事物。不要为了它而嘲笑一切,模仿单元测试所需的功能。
如果要抽象出对象上下文,请使用工作单元模式。