实体框架:如何扩展DbSet <type>?

use*_*850 5 c# entity-framework dbset

我正在尝试定义自己的DbSet,如:

public class MyDbSet<TEntity> : DbSet<TEntity>
    where TEntity : class
{
    public override TEntity Add(TEntity entity)
    {
      ....
Run Code Online (Sandbox Code Playgroud)

并在DbContext中使用它

    public MyDbSet<User> Users { get; set; }
Run Code Online (Sandbox Code Playgroud)

我面临的问题是Users在运行时将为null(因此无用)但我无法理解为什么.db.Users.Any(会抛出一些东西"value cannot be null"; 如果我替换和使用DbSet而不是

    public DbSet<User> Users { get; set; }
Run Code Online (Sandbox Code Playgroud)

一切正常.

有谁知道我是否以及如何解决这个问题所以我可以使用自己的派生类?

编辑:

在收到一些评论之后,我澄清了为什么我这样做:我希望能够轻松地从数据检索机制切换到另一个而无需更改代码.例如,如果我决定在内存中进行缓存(缓存只是一个例子,我可能也想改变其他一些东西)我只是覆盖Any/Find/...in MyDbSet和读取字典而不是查询数据库,剩下的代码不变.这样,代码将执行"常规"操作,而无需考虑如何检索数据.因此,如果有人可以指出一种方法来做到这一点而不扩展DbSet也将回答问题的类.

非常感谢

Dan*_*iel 1

我已经沿着这条路走了几次,并且理解希望以这种方式工作的愿望,但根据我的经验,这是不可行的,或者即使可行,也不值得付出努力。原因是许多不同的存储引擎(包括内存缓存)存在差异,无法轻松融入 EF。例如,DbSet 的简单内存缓存实现可能不支持事务、延迟加载或急切加载方案等。我的想法是,我希望能够在 Azure 表存储中进行交换。但排序、分页和查询功能并不像 SQL Server 那样丰富。有些查询可以使用 SQL 执行,但无法使用 Azure 表执行。最后,我总是相信,更换 EF 背后的持久性引擎的能力听起来很吸引人,但比仅仅实现几个类要复杂得多,而且在我的应用程序中通常不值得。

如果我想支持缓存并且正在使用 ASP.NET Web API,我会考虑使用 ASP.NET 缓存,以便在那时缓存 API 请求/响应。

如果我想要支持不同的关系数据库供应商,我会使用第 3 方 EF 提供程序:各种数据库的实体框架提供程序列表顺便说一句,它们确实链接到缓存和跟踪 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
     }

 }
Run Code Online (Sandbox Code Playgroud)

也就是说,对于我的大多数应用程序来说,当我考虑时,更换持久性引擎的能力并不是真正的要求。我的客户不“有些想要 SQL,有些想要 Azure 表”。这可能只是由于我们所做的工作类型所致,但最终,它最终成为我只是接受并直接编码到 EF 的依赖项。