我是EF和DBContext的新手,因此我正在寻找一些建议,以便使用EF,存储过程或SQL为WCF服务设置代码的最佳方式。
我有一个MVC3前端,它连接到数据访问(Oracle)的WCF服务层。实际的数据访问是通过一个单独的DAO类库。
我的目标是让服务层仅使用一个接口,在该接口上它可以调用一组方法来返回数据。我不希望服务层意识到我们正在使用EF进行查询,因为我可以在需要时用存储过程或纯SQL文本替换慢速EF位。
我有一个用于我的数据库IDB的接口,以及一个同时实现DBContext的IDB,MyDB的混合实现。然后,MyDb有一些名为MyStdDB和MySecureDB的派生类。当我想要接口时,我调用我的工厂方法,如果我需要一个标准或安全的数据库,然后将其返回到我的接口变量中。
WCF代码:
public List<string> GetAccount() {
IDB _db = DBFactory.GetInstance();
return _db.GetAccount();
}
DBFactory代码:
pubilc class DBFactory {
pubilc static IDB GetInstance()
{
if bSecure
return MySecureDB;
else
return MyStdDB;
}
}
所以,当我想要查询时,我想在我的服务调用中询问_db.GetAccount()。目前我已将此作为IDB接口的扩展方法添加。这样做的原因是为了防止服务看到我的EF实体,它允许将qqueries转换为逻辑文件,例如。类充满了CUSTOMER查询,类充满了ACCOUNT查询。
IDB代码:
public interface IDB : IDisposable
{
ObjectContext UnderlyingContext { get; }
int SaveChanges();
}
MyDB代码:
public class MyDB : DbContext, IDB
{
ObjectContext IDB.UnderlyingContext
{
get
{
return ((IObjectContextAdapter)this).ObjectContext;
}
}
int IDB.SaveChanges()
{
return SaveChanges();
}
public DbSet<Customer> Customer { get; set; }
}
扩展方法:
public static List<string> GetAccount(this IDB _db)
{
((MyDB)_db).Customer.AsNoTracking().First();
}
正如您所看到的,我必须将接口转换为具体对象,以便我可以访问EF实体。这是因为实体是在实现类而不是接口。 Extension方法在我的DAO类库中,因此当我的IDB implmentation改变时会改变,但我仍然不喜欢它。 有更好的方法吗?我在看DI吗?
对我来说,最大的推动力是:
答案 0 :(得分:2)
解决方法是将您的GetAccount
移至IDB
,而不是使用扩展程序:
public interface IDB : IDisposable
{
ObjectContext UnderlyingContext { get; }
List<string> GetAccount();
int SaveChanges();
}
它解决了您的问题,因为MyDB
将实现该方法,并且所有派生类也将使用实现。如果他们提供其他实现,他们将简单地覆盖它。
必须从服务中隐藏数据访问方法。我应该只 能够通过提供的方法访问数据 接口/扩展方法等。
但他们不是。如果方法/属性不公开,则隐藏该方法/属性,但目前您的任何服务都可以将IDB
转换为MyDB
并直接访问DbSet
。