我正在尝试定义自己的DbSet,例如:
public class MyDbSet<TEntity> : DbSet<TEntity>
where TEntity : class
{
public override TEntity Add(TEntity entity)
{
....
并在DbContext中使用它
public MyDbSet<User> Users { get; set; }
我面临的问题是Users
在运行时将为空(因此无用)但我无法理解为什么。
db.Users.Any(
之类的内容会抛出"value cannot be null"
;如果我替换并使用DbSet而不是像
public DbSet<User> Users { get; set; }
一切正常。
有人知道我是否以及如何解决这个问题,以便我可以使用自己的派生类?
修改
在收到一些评论之后,我澄清了为什么我这样做:我希望能够轻松地从数据检索机制切换到另一个而无需更改代码。例如,如果我决定在内存中进行缓存(缓存只是一个例子,我可能也想改变其他一些东西)我只是覆盖Any/Find/...
中的MyDbSet
并从字典中读取而不是查询数据库,而是保持其余代码不变。通过这种方式,代码将会定期执行#34;操作,而不关心如何检索数据。
因此,如果有人可以指出一种方法来做到这一点而不扩展也将回答问题的DbSet
类。
答案 0 :(得分:1)
我已经走过这条路几次了,并且理解让它以这种方式工作的愿望,但根据我的经验,这是不可行的,或者如果是,不值得努力。原因是许多不同的存储引擎(包括内存缓存)具有不能轻易融入EF的差异。例如,DbSet的一个简单的内存缓存实现可能不会遵循事务,懒惰或急切加载方案等。我的想法是我希望能够交换Azure表存储。但是,通过排序,分页和查询并不像SQL Server那样丰富。您可以使用SQL执行的某些查询无法使用Azure表。最后,我总是回过头来相信替换EF背后的持久性引擎的能力听起来很吸引人,但是比实现几个类更复杂 - 在我的应用程序中通常不值得。
如果我想支持缓存并且正在使用ASP.NET Web API,我会考虑使用ASP.NET缓存,以便在此时缓存API请求/响应。
如果我想要支持不同的关系数据库供应商,我会使用第三方EF提供商:A list of Entity Framework providers for various databases顺便提一下,他们确实链接到缓存和跟踪EF提供商 - 不知道这是否适用于新的EF。
如果我想在数据层内部进行缓存,或者多个存储引擎完全不同(即Mongo,Azure和SQL),我会在EF层“上方”进行缓存。像这样:
public interface ISomeDataProvider
{
SomeType Find(int id);
....
}
public class EfDataProvider : ISomeDataProvider
{
private SomeAppDbContext db = new SomeAppDbContext();
public SomeType Find(int id){
return db.SomeTypes.Find(id);
}
}
public class AzureTableDataProvider : ISomeDataProvider
{
public SomeType Find(int id){
return //Azure Table code
}
}
public class CachingDataProvider : ISomeDataProvider
{
private ISomeDataProvider source;
private static IList<SomeType> cache = new List<SomeType>(); //List used here, but could use .NET Cache, Redis, etc.
public CachingDataProvider(ISomeDataProvider source){
this.source = source;
}
public SomeType Find(int id){
var result = cache.SingleOrDefault(x=>x.Id == id)
if(result == null){
result = source.SingleOrDefault(x=>x.Id == id)
if(result != null) cache.Add(result); //Again, trivial cache example. Cache expiration, refresh, loading, etc. should be considered per-app
}
return result
}
}
也就是说,对于我的大多数应用程序,当我考虑它时,交换持久性引擎的能力并不是真正的要求。我的客户不“有些想要SQL,有些想要Azure表”。这可能只是由于我们所做的工作类型,但最终,它最终成为我只接受并直接编码到EF的依赖。