简体   繁体   English

在Entity Framework Core上使用using()封装DbContext

[英]Encapsulating DbContext with using() on Entity Framework Core

I wanted to try to expose a DbContext instance through a get statement: 我想尝试通过get语句公开DbContext实例:

public class SomeContext : DbContext
{
    public SomeContext()
    {

    }

    public DbSet<SomeModel1> SomeModel1s { get; set; }
    public DbSet<SomeModel2> SomeModel2s { get; set; }

   //etc
}

public class SomeInterfaceImplementation
{
    SomeContext ContextInstance { get; }
    //etc
}

But instead of using ContextInstance as a singleton, I want to do something so that calling ContextInstance actually does something like: 但是,而不是使用ContextInstance作为一个单身,我想要做的事,这样调用ContextInstance实际上不会是这样的:

someVar = ContextInstance.SomeModel1s.Where(x => x.SomeID == externalID).OrderBy(x => x.SomeProperty).ToList();
//becomes the same as
using (var db = new SomeContext())
{
  someVar = db.SomeModel1s.Where(x => x.SomeID == externalID).OrderBy(x => x.SomeProperty).ToList();
}

basically, I just want to hide the using statement and create and dispose an instance of SomeContext every time ContextInstance is called. 基本上,我只想隐藏using语句,并在每次调用ContextInstance时创建并配置SomeContext的实例。 Hopefully I make sense. 希望我有道理。 Does anyone have something in mind to do this? 有人在想什么吗?

This may not be a very good idea, because there are some standard scenarios with DbContext . 这可能不是一个好主意,因为DbContext有一些标准方案。 For example DbContext implements Unit of Work pattern so the using may be necessary. 例如DbContext实现工作模式的单位 ,因此using可能是必要的。

But you can make what you want although is't not easy. 但是,尽管并非易事,但您可以做出自己想要的事情。

You need implement IQueryProvider<TEntity> interface and especially the generic method Execute : 您需要实现IQueryProvider<TEntity>接口,尤其是通用方法Execute

public class EFDbSetProvider<TEntity> : IQueryableProvider<TEntity>
where TEntity : class
{
    public TResult Execute<TResult>(Expression expression)
    {
        using (dbContext = new DbContext())
        {
             return (TResult) dbContext.Set<TEntity>.Provider.Execute(expression);
        }
    }
}

Also you'll need implement corresponding IQueryable<TEntity> interface, but as I can see this implementation should be very simple. 另外,您将需要实现相应的IQueryable<TEntity>接口,但是正如我所看到的,该实现应该非常简单。

public class EFQueryable<TEntity> : IQueryable<TEntity>
{
    . . .
}

public static class SomeContext
{
    public static EFQueryable<SomeModel1> SomeModels1 { get; set; }
    public static EFQueryable<SomeModel2> SomeModels2 { get; set; }
}

someVar = SomeContext.SomeModel1s.Where(x => x.SomeID == externalID).OrderBy(x => x.SomeProperty).ToList();

The Execute method will be called from ToList , then it will create DbContext and pass the assemblied expression to DbSet<TEntity>.Provider.Execute . 将从ToList调用Execute方法,然后它将创建DbContext并将组合的表达式传递给DbSet<TEntity>.Provider.Execute

You may google "custom LINQ providers" or "IQueryable implementation example". 您可以使用Google“自定义LINQ提供程序”或“ IQueryable实现示例”。 Fe I found the article Implementing a ustom LINQ provider so you can start here for details. 例如,我发现了文章实施ustom LINQ提供程序,因此您可以从此处开始以获取详细信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM