【问题标题】:Entity framework: how to extend DbSet<type>?实体框架:如何扩展 DbSet<type>?
【发布时间】:2014-04-28 00:17:55
【问题描述】:

我正在尝试定义自己的 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; }

一切正常。

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

编辑:

在收到一些 cmets 后,我澄清了我这样做的原因:我希望能够在不更改代码的情况下轻松地从数据检索机制切换到另一种机制。例如,如果我决定在内存中进行缓存(缓存只是一个示例,可能我还想更改其他一些东西)我只是覆盖MyDbSet 中的Any/Find/... 并从字典中读取而不是查询数据库,其余代码保持不变。这样,代码将执行“常规”操作,而无需考虑如何在后面检索数据。 因此,如果有人可以在不扩展 DbSet 类的情况下指定一个方法来执行此操作,那也将回答这个问题。

非常感谢

【问题讨论】:

  • 你为什么要这样从 DbSet 派生?听起来你真的不能这样做,因为你不能在 DbContext 中覆盖 DBSet 的实例化。
  • 最重要的是,我想知道真正的用例。在一个结构合理的应用中——我从来没有发现需要这样做。
  • 请查看更新后的问题,了解我为什么要这样做。

标签: c# entity-framework dbset


【解决方案1】:

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

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

如果我想要支持不同的关系数据库供应商,我会使用第 3 方 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 Tables”。这可能只是由于我们所做的工作类型,但最终,它最终成为我接受并直接编码到 EF 的依赖项。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-10
    • 1970-01-01
    • 2014-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多