Entity Framework:如何扩展DbSet<type>?

5

我正在尝试定义自己的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(这样的语句会抛出"值不能为 null"的异常;如果我使用DbSet替换,例如:
    public DbSet<User> Users { get; set; }

一切正常运行。

有人知道如何解决这个问题,以便我可以使用自己派生的类吗?

编辑:

收到一些评论后,我澄清了为什么要这样做:我想能够轻松地从一种数据检索机制切换到另一种,而不必更改代码。例如,如果我决定在内存中进行缓存(缓存只是一个例子,可能我还想改变其他一些东西),我只需在MyDbSet中覆盖 Any/Find/...,从字典中读取而不是查询数据库,而其余的代码保持不变。这样,代码将执行“常规”操作,而不关心数据检索背后的细节。 因此,如果有人可以指出一种方法来在不扩展DbSet类的情况下实现这一点,那也将回答这个问题。

非常感谢


你为什么要这样从DbSet派生?听起来好像你真的做不到,因为你无法覆盖DbContext中DBSet的实例化。 - Federico Berasategui
1
在顶部,我想知道真正的使用情况。在一个结构良好的应用程序中,我从来没有发现需要这样做。 - TomTom
请查看更新的问题,了解我想要这样做的原因。 - user3346850
1个回答

1
我曾多次经历过这样的情况,理解想要实现这种方式的愿望,但是根据我的经验,这并不可行,或者即使可行,也不值得付出努力。原因在于许多不同的存储引擎(包括内存缓存)具有EF无法轻松适应的差异。例如,一个微不足道的内存缓存的DbSet实现可能不支持事务、延迟或急切加载等。我的想法是,我希望能够切换到Azure Table Storage。但是,与SQL Server相比,它的排序、分页和查询功能不如丰富。最终,我总是认为,在EF后面交换持久化引擎的能力听起来很有吸引力,但比实现几个类要复杂得多,而且通常不值得在我的应用程序中实现。
如果我想支持缓存,并且正在使用ASP.NET Web API,我会考虑使用ASP.NET缓存,以便在该点缓存API请求/响应。
如果我需要支持不同的关系型数据库供应商,我将使用第三方EF提供程序:各种数据库的Entity Framework提供程序列表。顺便说一句,它们链接到缓存和跟踪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 的一个依赖项。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接